calling a script from Binary in chroot mode,not working - c

Part of a program named =program.c
int memoryPercent()
{
int memoryPercent=0;
FILE *pipe1 = NULL;
pipe1=popen("/home/jatin/scripts/memoryPercent.sh","r");
if(!pipe1)
{
snmp_log(LOG_ERR,"popen failed in temp(),errno:%d\n",errno);
return -1;
}
if( fscanf(pipe1,"%d",&memoryPercent) != 1)
{
snmp_log(LOG_ERR,"fscanf failed in temp fun(),errno:\n");
return -2;
}
pclose(pipe1);
return memoryPercent;
}
above is my calling code /home/jatin/scripts/memoryPercent.sh
on this location a scripts is given and it is returning a INTEGER value.
in UBUNTU 12.04 when I compile and execute this code it is running perfectly.
but in my VM-WARE
I have copied all the necessary dependencies at the location /var/snmp3 and executing this binary with CHROOT the syntax is
/usr/sbin/chroot /var/snmp3/ /usr/local/bin/program
it is showing value "-1" only !!
Can anyone tell me what I am missing ?
the script is at the same location in /var/snmp3/home/jatin/scripts/memoryPercent.sh
as well as /home/jatin/scripts/memoryPercent.sh in 775 mode....

Try running the script manually from a chrooted shell.
I think you are missing the shell used by memoryPercent.sh. Have you copied the shell to the chrooted environment?

Related

GetModuleHandleW / A - not working. Returning null every call excluding empty string

#include <Windows.h>
int main(){
printf("Enter name of program. \n");
char prog[300];
scanf("%s", prog);
HMODULE hModule = GetModuleHandleW((LPCWSTR)prog);
if (hModule){
IMAGE_DOS_HEADER* pIDH = (IMAGE_DOS_HEADER*)hModule;
IMAGE_NT_HEADERS* pNTH =(IMAGE_NT_HEADERS*)((BYTE*)pIDH + pIDH->e_lfanew);
IMAGE_OPTIONAL_HEADER pOPH = (IMAGE_OPTIONAL_HEADER)pNTH->OptionalHeader;
IMAGE_DATA_DIRECTORY* pIDD = (IMAGE_DATA_DIRECTORY*)pOPH.DataDirectory;
printf("%x", pIDD->VirtualAddress);
}
else {
printf("Error");
}
return 0;
}
That's my basic script for now only to check if I get into the IMAGE_DATA_DIRECTORY.
My goal is to print every dll and all of it's imported functions of a certain running process - GetModuleHandleA / W.
Every call its returning null - printing "Error" as I checked, excluding the empty call in which it prints '0' for some reason..
Besides the obvious (LPCWSTR)prog casting bug, GetModuleHandle is never going to work because it only handles modules in the current process.
Call CreateToolhelp32Snapshot to get a list of all processes and then call CreateToolhelp32Snapshot again to get the modules of a specific process. Note that you cannot read the DOS/NT headers of a remote process directly, you would have to use ReadProcessMemory.
DataDirectory is an array, you have to specify the directory you are interested in (resource, import, export etc.).

gtk filechooser with msys2 return not correct values

in my project i compiled a gtk-gui with msys2. I think everything works fine except for one thing.
If i start my application and try to choose a file with the filechooser i recognized that in the first attempt the return value of the
gtk_file_chooser_get_current_folder() is NULL. In the second try the return value seems to be correct but the last folder is missing.
Compiling and running it under linux leads to no problem. I use glade in combination with gtk.
I'm not sure what kind of code snipped i should post here, but if you want to see a specific thing i will upload it of course.
I would be very pleased about some suggestions.
At first i initialize the FileChooserWidget:
WCO_GUI_Ref()->MyFileChosserButton1 = GTK_WIDGET(gtk_builder_get_object(WCO_GUI_Ref()->MyBuilder, "MyFileChosserButton1"));
If you choose a folder with the FileChooser a function is called which stores the return value and print it out:
WCO_PDF_SetFoldername(WCO_ENTRY(WCO_GUI_Get(folder_name)));
The WCO_GUI_Get() function returns a void pointer which is casted by the WCO_ENTRY() macro. In this function the i call gtk_file_chooser_get_current_folder() like this:
void *WCO_GUI_Get(int id)
{
void *ret;
switch(id)
{
case 0: ret = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(WCO_GUI_Ref()->MyFileChosserButton1)); break;
default: break;
}
return ret;
}
If i place this debug code:
printf("%s", WCO_ENTRY(WCO_GUI_Get(folder_name)) );
The Output of it in the first try is (null) and after the first one i got a output like this C:\usr\documents\ but the actual selected folder is C:\usr\documents\test\

chdir(getenv("HOME") returns Bad address

char *home = getenv("HOME");
if (!strcmp(t->argv[0], "cd")) {
if (!t->argv[1]) {
chdir(home);
}
if (chdir(t->argv[1])) {
perror(t->argv[1]);
}
}
what this is supposed to do is run the cd command with the provided argument, and if there is no argument provided then return to the home directory. if i call cd without an argument, chdir prints "Bad address". i dont know why, considering i printed the value that getenv("HOME") returns and entered that path manually in my shell and it worked fine. why does it work when i provide the value but not when getenv provides it?
I also cant manually code a path for home either because it has to run on other machines. i need it to work with getenv("HOME").
i was being an idiot, as #dimich pointed out. the first chdir worked fine, but the second if statement should be an else if.
new code:
char *home = getenv("HOME");
if (!strcmp(t->argv[0], "cd")) {
if (!t->argv[1]) {
chdir(home);
} else if (chdir(t->argv[1])) {
perror(t->argv[1]);
}
}

Mingw produces x86 program which only successfully runs as Administrator- x64 and VS(x86 and x64) versions fine

I was taking a look at this Github project: https://github.com/LloydLabs/delete-self-poc
This project uses the SetFileInformationByHandle API (https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle) in a somewhat creative way to allow the deletion from disk of a locked file. I am attempting to implement this as part of a larger program, however I have ran into an issue when compiling for x86. I use mingw-w64 on a debian machine to compile my program and when doing compatibility checks for x86, I found a very strange issue.
#include "main.h"
static
HANDLE
ds_open_handle(
PWCHAR pwPath
)
{
return CreateFileW(pwPath, DELETE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
static
BOOL
ds_rename_handle(
HANDLE hHandle
)
{
FILE_RENAME_INFO fRename;
RtlSecureZeroMemory(&fRename, sizeof(fRename));
// set our FileNameLength and FileName to DS_STREAM_RENAME
LPWSTR lpwStream = DS_STREAM_RENAME;
fRename.FileNameLength = sizeof(lpwStream);
RtlCopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream));
return SetFileInformationByHandle(hHandle, FileRenameInfo, &fRename, sizeof(fRename) + sizeof(lpwStream));
}
static
BOOL
ds_deposite_handle(
HANDLE hHandle
)
{
// set FILE_DISPOSITION_INFO::DeleteFile to TRUE
FILE_DISPOSITION_INFO fDelete;
RtlSecureZeroMemory(&fDelete, sizeof(fDelete));
fDelete.DeleteFile = TRUE;
return SetFileInformationByHandle(hHandle, FileDispositionInfo, &fDelete, sizeof(fDelete));
}
int
main(
int argc,
char** argv
)
{
WCHAR wcPath[MAX_PATH + 1];
RtlSecureZeroMemory(wcPath, sizeof(wcPath));
// get the path to the current running process ctx
if (GetModuleFileNameW(NULL, wcPath, MAX_PATH) == 0)
{
DS_DEBUG_LOG(L"failed to get the current module handle");
return 0;
}
HANDLE hCurrent = ds_open_handle(wcPath);
if (hCurrent == INVALID_HANDLE_VALUE)
{
DS_DEBUG_LOG(L"failed to acquire handle to current running process");
return 0;
}
// rename the associated HANDLE's file name
DS_DEBUG_LOG(L"attempting to rename file name");
if (!ds_rename_handle(hCurrent))
{
DS_DEBUG_LOG(L"failed to rename to stream");
return 0;
}
DS_DEBUG_LOG(L"successfully renamed file primary :$DATA ADS to specified stream, closing initial handle");
CloseHandle(hCurrent);
// open another handle, trigger deletion on close
hCurrent = ds_open_handle(wcPath);
if (hCurrent == INVALID_HANDLE_VALUE)
{
DS_DEBUG_LOG(L"failed to reopen current module");
return 0;
}
if (!ds_deposite_handle(hCurrent))
{
DS_DEBUG_LOG(L"failed to set delete deposition");
return 0;
}
// trigger the deletion deposition on hCurrent
DS_DEBUG_LOG(L"closing handle to trigger deletion deposition");
CloseHandle(hCurrent);
// verify we've been deleted
if (PathFileExistsW(wcPath))
{
DS_DEBUG_LOG(L"failed to delete copy, file still exists");
return 0;
}
DS_DEBUG_LOG(L"successfully deleted self from disk");
return 1;
}
When compiling the base code found in the linked repository (and shown above) as x86, attempting to run the program fails at the SetFileInformationByHandle call in the ds_rename_handle function. Calling GetLastError() returns 123:
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
The very bizarre part is that the program succeeds when ran from an Administrator prompt. Even stranger, compiling the same code for x64 works both in a normal and an Administrator prompt.
As a sanity check I copied the code verbatim over to VS2019 and compiled there, and the resulting x86 program was able to run without Administrator privileges.
The only changes to the source code made on the debian system were made in the header file:
#pragma once
#pragma comment(lib, "Shlwapi.lib")
#include <Windows.h>
#include <shlwapi.h>
#include <stdio.h>
#include <stdlib.h>
#define DS_STREAM_RENAME L":wtfbbq"
#define DS_DEBUG_LOG(msg) wprintf(L"[LOG] - %s\n", msg)
Where <Windows.h> was changed to <windows.h> and the DS_DEBUG_LOG line changed to %ls so that the entire log message would print.
The GCC command used to compile for x86 was:
i686-w64-mingw32-gcc main.c -o delete32.exe -s -DUNICODE -Os -lshlwapi
I have tried removing all switches and compiling and it still fails.
As a note, the shlwapi library is only required for the very last call in main(), PathFileExistsW. I have commented out that portion and removed shlwapi from imports and from the gcc command to no effect.
The x64 gcc command which succeeded was:
x86_64-w64-mingw32-gcc main.c -o delete32.exe -s -DUNICODE -Os -lshlwapi
In the issues tab of the github repo there are some mentions of errors in the code which I have looked at separately. However I would desperately like to know why mingw is causing an issue with the 32 bit version of this program. Unfortunately "just compile with VS" isn't an option, as I use a program to generate and compile the program that this bit of code will be part of on my linux machine.
Thanks for any insight.
RtlCopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream)); writes 4 or 8 bytes into a 2 byte buffer! Who knows where the remaining bytes are going, the program behavior is probably undefined.
The concept of deleting a running exe like this might work but the code indicates that the author does not have a full understanding of Windows and C. You are better off rewriting it from scratch...
Edit:
After playing with your uploaded files I can with confidence say that it is the lack of a application manifest that causes it to fail when it is not elevated. Your vc file has a requestedExecutionLevel element which gives it Vista operating system context. If you remove the manifest resource in the vc exe it stops working. If you add a manifest to the mingw exe it starts working.
the ds_rename_handle function is wrong implemented.
the FILE_RENAME_INFO is variable size structure.
as result declaration
FILE_RENAME_INFO fRename;
almost always wrong (it will ok only if FileName containing 1 or 2 symbols)
really we need first calculate FileNameLength and then allocate PFILE_RENAME_INFO based on this
as example:
ULONG FileNameLength = (ULONG)wcslen(DS_STREAM_RENAME) * sizeof(WCHAR);
ULONG dwBufferSize = FIELD_OFFSET(FILE_RENAME_INFO, FileName) + FileNameLength;
PFILE_RENAME_INFORMATION fRename = (PFILE_RENAME_INFORMATION)alloca(dwBufferSize);
so complete code for ds_rename_handle can be next:
ULONG ds_rename_handle(HANDLE hHandle, PCWSTR DS_STREAM_RENAME)
{
ULONG FileNameLength = (ULONG)wcslen(DS_STREAM_RENAME) * sizeof(WCHAR);
ULONG dwBufferSize = FIELD_OFFSET(FILE_RENAME_INFO, FileName) + FileNameLength;
PFILE_RENAME_INFO fRename = (PFILE_RENAME_INFO)alloca(dwBufferSize);
fRename->ReplaceIfExists = TRUE;
fRename->RootDirectory = 0;
fRename->FileNameLength = FileNameLength;
memcpy(fRename->FileName, DS_STREAM_RENAME, FileNameLength);
return SetFileInformationByHandle(hHandle, FileRenameInfo,
fRename, dwBufferSize) ? NOERROR : GetLastError();
}
but documentation of FILE_RENAME_INFO is very bad. unclear - in what form - full pathname, file name or a relative pathname - must be FileName ?!
from my research - it must be full pathname only (not file name) or begin with a colon : ( The new name for the stream )
much more better use NtSetInformationFile with FileRenameInformation
compare description of FILE_RENAME_INFORMATION structure with FILE_RENAME_INFO !
here exist detailed description - in what form FileName it should be.
so i always use
NTSTATUS ds_rename_handle_nt(HANDLE hHandle, PCWSTR DS_STREAM_RENAME)
{
ULONG FileNameLength = (ULONG)wcslen(DS_STREAM_RENAME) * sizeof(WCHAR);
ULONG dwBufferSize = FIELD_OFFSET(FILE_RENAME_INFO, FileName) + FileNameLength;
PFILE_RENAME_INFORMATION fRename = (PFILE_RENAME_INFORMATION)alloca(dwBufferSize);
fRename->ReplaceIfExists = TRUE;
fRename->RootDirectory = 0;
fRename->FileNameLength = FileNameLength;
memcpy(fRename->FileName, DS_STREAM_RENAME, FileNameLength);
IO_STATUS_BLOCK iosb;
return NtSetInformationFile(
hHandle, &iosb, fRename, dwBufferSize, FileRenameInformation);
}

GNU BFD on binary results to "No such file or directory" (binary not executed)

There is this piece of C code that is used extract info from binaries:
bincode_t *initialize_bincode(const char *file)
{
bfd *abfd;
bincode_t *bin;
//char *target = "x86_64-unknown-linux-gnu";
char *target = "i686-pc-linux-gnu";
bfd_init();
if (!bfd_set_default_target(target)) {
bs_dbgmsg(" (!) bfd_set_default_target()\n");
return NULL;
}
if ((abfd = bfd_openr(file, target)) == NULL) {
bs_dbgmsg(" (!) bfd_openr(): %s\n", file);
return NULL;
}
if (!bfd_check_format(abfd, bfd_object)) {
//isolated the error to be here (through simple print debugging)
bs_dbgmsg(" (!) bfd_check_format()\n");
printf("Error: %s", bfd_errmsg(bfd_get_error()));
bfd_close(abfd);
return NULL;
}
if((bin = malloc(sizeof(bincode_t))) == NULL) {
bs_errmsg(" (!) malloc(): bin\n");
exit(EXIT_FAILURE);
}
I ran this code on Linux against 2 Windows binary samples. However, one of sample results in an error of
Error: File format not recognized ... Section flag STYP_DSECT (0x1) ignored
The file command on both samples results in the following output:
fc671a044d48bffe519a89b06d289d83f52958cb: PE32 executable (GUI) Intel
80386, for MS Windows
and
fe0c189a5067a2dfe46bad1c2cedaa5b7bbc6a20: PE32 executable (DLL) (GUI)
Intel 80386, for MS Windows
The second binary (DLL) results into the error. My question is, why did this happen? What can I do to resolve this? I would like the code to also "see" the DLL binary.
I plugged the DLL binary into gdb and indeed gdb didn't recognize the file. GDB output:
...not in executable format: File format not recognised
Edit 1:
Added code and completed error message output. Kindly note that I am a C beginner.
Edit 2:
As suggested in the comments, I have used bfd_errmsg(bfd_get_error()) and included the output above.

Resources