I've been trying to setup SEH on x64 windows using gcc by calling the RtlAddFunctionTable. Unfortunately, the API call returns success but my handler doesn't seem to ever be called. And I can't find out what's wrong. My small example is:
EXCEPTION_DISPOSITION catchDivZero( struct _EXCEPTION_RECORD* rec
, void* arg1 __attribute__((unused))
, struct _CONTEXT* ctxt __attribute__((unused))
, void* arg2 __attribute__((unused))
)
{
printf("Exception will be handled!\n");
return ExceptionContinueSearch;
}
HMODULE GetCurrentModule()
{ // NB: XP+ solution!
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)GetCurrentModule,
&hModule);
return hModule;
}
typedef struct {
UINT8 Version : 3;
UINT8 Flags : 5;
UINT8 SizeOfProlog;
UINT8 CountOfUnwindCodes;
UINT8 FrameRegister : 4;
UINT8 FrameRegisterOffset : 4;
ULONG ExceptionHandler;
} UNWIND_INFO;
/* Hack, for bug in ld. Will be removed soon. */
#if defined(__GNUC__)
#define __ImageBase __MINGW_LSYMBOL(_image_base__)
#endif
/* Get the end of the text section. */
extern char etext[] asm("etext");
/* Get the base of the module. */
/* This symbol is defined by ld. */
extern IMAGE_DOS_HEADER __ImageBase;
static UNWIND_INFO info[1];
static RUNTIME_FUNCTION handlers[1];
#define base (ULONG)((HINSTANCE)&__ImageBase)
int main()
{
HANDLE hProcess = GetCurrentProcess();
HMODULE hModule = GetCurrentModule();
MODULEINFO mi;
GetModuleInformation(hProcess, hModule, &mi, sizeof(mi));
printf( "Module: 0x%.8X (0x%.8X) 0x%.8X |0x%.8X| [0x%.8X] {0x%.8X}\n\n"
, mi.lpBaseOfDll
, base
, (char*)etext
, mi.SizeOfImage
, &catchDivZero
, (ULONG)(&catchDivZero - base)
);
printf("Building UNWIND_INFO..\n");
info[0].Version = 1;
info[0].Flags = UNW_FLAG_EHANDLER;
info[0].SizeOfProlog = 0;
info[0].CountOfUnwindCodes = 0;
info[0].FrameRegister = 0;
info[0].FrameRegisterOffset = 0;
info[0].ExceptionHandler = (ULONG)(&catchDivZero - base);
printf("Created UNWIND_INFO at {0x%.8X}\n", info[0].ExceptionHandler);
printf("Building SEH handlers...\n");
handlers[0].BeginAddress = 0;
handlers[0].EndAddress = (ULONG)(etext - base);
handlers[0].UnwindData = (ULONG)((char*)info - base);
printf("Adding SEH handlers to .pdata..\n");
printf("Handler Unwind: 0x%.8X\n", &info);
printf( "Handler Info:: s: 0x%.8X, e: 0x%.8X, u: 0x%.8X\n"
, handlers[0].BeginAddress
, handlers[0].EndAddress
, handlers[0].UnwindData
);
if (RtlAddFunctionTable(handlers, 1, (DWORD64)base))
{
printf("Hook succeeded.\nTesting..\n");
printf("Things to do: %i\n", 12 / 0);
}
else
{
printf("Hook failed\n");
DWORD result = GetLastError();
printf("Error code: 0x%.8X\n", result);
}
}
However when called the output I get is:
> .\a.exe
Module: 0x00400000 (0x00400000) 0x00402FF0 |0x00022000| [0x00401530] {0x00001530}
Building UNWIND_INFO..
Created UNWIND_INFO at {0x00001530}
Building SEH handlers...
Adding SEH handlers to .pdata..
Handler Unwind: 0x00407030
Handler Info:: s: 0x00000000, e: 0x00002FF0, u: 0x00007030
Hook succeeded.
Testing..
The message in my handler is never printed.
Any help/pointers would be greatly appreciated.
RtlAddFunctionTable() adds a dynamic function table; if there already is a static function table (.pdata section) for the base address, the RtlAddFunctionTable() calls succeeds, but the static function table still takes precedence.
You need to allocate memory outside the image range, e.g. using VirtualAlloc(), and have your code and runtime table and unwind info there. The address of allocated memory is the base address for all the RVAs in the tables, and needs to be passed to RtlAddFunctionTable().
You can experiment with RtlLookupFunctionEntry() to see if the function table entry is found for a given address.
Sample code showing RtlAddFunctionTable() in action is at https://pmeerw.net/blog/programming/RtlAddFunctionTable.html.
Didn't you forget to register your handler with call to SetUnhandledExceptionFilter (if you use SEH as stated in your post) or AddVectoredExceptionHandler (if you decide to switch to VEH)? In your code you add information about the handler but do not register it.
I have tested your sample with the change of the handler itself:
LONG WINAPI catchDivZero(EXCEPTION_POINTERS * ExceptionInfo)
{
printf("Exception will be handled!\n");
return ExceptionContinueSearch;
}
and adding the code:
if (::AddVectoredExceptionHandler(TRUE, catchDivZero))
{
printf("Set exception handler.\nContinuing..\n");
}
else
{
printf("Setting exception handler failed\n");
DWORD result = GetLastError();
printf("Error code: 0x%.8X\n", result);
return 1;
}
just before the call to RtlAddFunctionTable.
Now the message from the handler is printed.
To remove the handler use:
::RemoveVectoredExceptionHandler(catchDivZero);
Hope it helps.
Note: as an alternative you may use SetUnhandledExceptionFilter(catchDivZero)). Keep in mind that it's not that useful for debugging:
After calling this function, if an exception occurs in a process that
is not being debugged, and the exception makes it to the unhandled
exception filter, that filter will call the exception filter function
specified by the lpTopLevelExceptionFilter parameter.
With VEH way we can debug the handler function right in IDE, with SEH we can not (there is probably a solution to this but I do not know about it) so I've proposed VEH as the main solution.
Related
I know this is not adequate for stack overflow question, but ..
This is a function in scripts/dtc/libfdt/fdt_ro.c of u-boot v2021.10.
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp)
{
int poffset;
const struct fdt_property *prop;
printf("uuu0 nodeoffset = 0x%x, name = %s, namelen = %d\n", nodeoffset, name, namelen);
prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
&poffset);
//printf("uuu1 prop = 0x%lx, *lenp = 0x%x, poffset = 0x%x\n", prop, *lenp, poffset);
if (!prop)
return NULL;
/* Handle realignment */
if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
When I build the program, if I uncomment the second printf, the compiler seg-faults.
I have no idea. Is it purely compiler problem(I think so it should never die at least)? or can it be linked to my fault somewhere in another code? Is there any method to know the cause of the segfault? (probably not.).
If you're getting a segmentation fault when running the compiler itself, the compiler has a bug. There are some errors in your code, but those should result in compile-time diagnostics (warnings or error messages), never a compile-time crash.
The code in your question is incomplete (missing declarations for fdt_get_property_namelen_, printf, NULL, etc.). Reproduce the problem with a complete self-contained source file and submit a bug report: https://gcc.gnu.org/bugzilla/
printf("uuu1 prop = 0x%lx, *lenp = 0x%x, poffset = 0x%x\n", prop, *lenp, poffset);
prop is a pointer, so I'd use %p instead of %lx
lenp is a pointer, so I'd make sure that it points to valid memory
I'm trying to use dlmopen() in order to launch the same .so file with few instances.
Because I the shared object includes few static methods, I have to use dlmopen() in order to create due instances of it.
For each instance (all in the same thread,if it matters), in the constructor I use:
handle_ = dlmopen(LM_ID_NEWLM, "path_to_so", RTLD_LAZY | RTLD_DEEPBIND);
and I get no errors, I'm even able to use dlsym() to invoke functions from the so file:
int (*function_name)(int, const char *);
function_name = (int (*)(int, const char *))(unsigned long)dlsym(handle_, "function_name");
The thing that happens is when I try to use any kind of "zmq send" method (the receive works well) I get:
terminate called after throwing an instance of 'zmq::error_t'
what(): Interrupted system call
even after I terminate the object of the dlmopen() and the object that created them.
Has anyone encountered this kind of problem? I tried to change the flags of the dlmopen() with no luck.
This is the code for zmq_send():
inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
{
int nbytes = zmq_send (ptr, buf_, len_, flags_);
if (nbytes >= 0)
return (size_t) nbytes;
if (zmq_errno () == EAGAIN)
return 0;
throw error_t ();
}
I'm trying to implement an injection of my 64-bit DLL into a 64-bit process. My host process calls CreateRemoteThread with a thread subroutine pointing to LoadLibrary. The DLL later unloads itself "from within" by calling FreeLibraryAndExitThread.
My goal is to know if the injected LoadLibrary call succeeded. For that unfortunately I can't use GetExitCodeThread from within my (host) process since returned 64-bit HMODULE handle is truncated to by a remote thread to DWORD. And I don't want to use Tool Help APIs as they will introduce a race condition.
So thus I was wondering about the lower 32-bits of the HMODULE returned by LoadLibrary in a 64-bit process -- can I reliably assume that its lower 32-bits will not be 0's for a valid handle?
PS. I don't need the HMODULE handle itself, all I need to know if LoadLibrary succeeded or not.
Edit. The call from my host process is done as such (in a very concise pseudo-code -- no error checking):
CreateRemoteThread(hProcess, 0, 0,
GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"),
pVmAddressOfMyDllsPathWrittenWith_WriteProcessMemory, 0, 0);
Can I reliably assume that its lower 32-bits will not be 0's for a valid handle?
No you cannot. An HMODULE is just the same in 64 bit as it is in 32 bit. It is the base address of the loaded module. So there is no reason why a valid HMODULE would have to have non-zero low order bits.
It's very simple for you to confirm this. Create a 64 bit DLL with an IMAGEBASE set to, for instance, 0x0000000100000000. Load that DLL, and inspect the value of the returned HMODULE.
instead CreateRemoteThread with a thread subroutine pointing to LoadLibraryW we can inject tiny shell code to remote process which first call LoadLibraryW and than, if it fail, GetLastError - as result remote thread return error code (0 if no error) - and you will be know exactly - are LoadLibrary ok and if not - have error code. the 64 asm code can be:
CONST segment
SHELLDATA struct
LoadLibrary DQ ?
GetLastError DQ ?
SHELLDATA ends
public RemoteThreadProc_begin
public RemoteThreadProc_end
RemoteThreadProc_begin:
RemoteThreadProc proc
nop
nop
nop
call ##0
___ SHELLDATA <>
##0:
xchg [rsp],rbp
sub rsp,20h
call SHELLDATA.LoadLibrary[rbp]
test rax,rax
jz ##1
xor eax,eax
##2:
add rsp,20h
pop rbp
ret
##1:
call SHELLDATA.GetLastError[rbp]
jmp ##2
RemoteThreadProc endp
RemoteThreadProc_end:
CONST ends
and c++ code:
extern "C"
{
extern UCHAR RemoteThreadProc_begin[], RemoteThreadProc_end[];
}
enum INJECT_PHASE {
fOpenProcess, fVirtualAlloc, fWriteProcessMemory, fCreateRemoteThread, fMax
};
ULONG injectDll(ULONG dwprocessId, PCWSTR dllFilePath, INJECT_PHASE& phase)
{
ULONG err = 0;
struct SHELLDATA
{
__int64 code;
PVOID LoadLibrary, GetLastError;
};
if (HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE, FALSE, dwprocessId))
{
SIZE_T cbStr = (wcslen(dllFilePath) + 1) * sizeof(WCHAR);
SIZE_T cbCode = ((RemoteThreadProc_end - RemoteThreadProc_begin) + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
union {
PVOID RemoteAddress;
PBYTE pbRemote;
PTHREAD_START_ROUTINE lpStartAddress;
};
if (RemoteAddress = VirtualAllocEx(hProcess, 0, cbStr + cbCode, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
{
union {
PVOID pv;
PBYTE pb;
SHELLDATA* ps;
};
pv = alloca(cbStr + cbCode);
memcpy(pv, RemoteThreadProc_begin, cbCode);
memcpy(pb + cbCode, dllFilePath, cbStr);
HMODULE hmod = GetModuleHandle(L"kernel32");
ps->GetLastError = GetProcAddress(hmod, "GetLastError");
ps->LoadLibrary = GetProcAddress(hmod, "LoadLibraryW");
if (WriteProcessMemory(hProcess, RemoteAddress, pv, cbStr + cbCode, 0))
{
if (HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, lpStartAddress, pbRemote + cbCode, 0, 0))
{
phase = fMax;
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &err);
CloseHandle(hThread);
}
else
{
phase = fCreateRemoteThread;
err = GetLastError();
}
}
else
{
phase = fWriteProcessMemory;
err = GetLastError();
}
VirtualFreeEx(hProcess, RemoteAddress, 0, MEM_RELEASE);
}
else
{
phase = fVirtualAlloc;
err = GetLastError();
}
CloseHandle(hProcess);
}
else
{
phase = fOpenProcess;
err = GetLastError();
}
return err;
}
I want to make like a function with an argument stdvector::<std::string> of process names and std::vector<std::string> of .dll's to find in them and feed it into a function and get like PROCESSENTRY32 info std::vector<PROCESSENTRY32> returned of anything that matches the names.
You can google but won't find much as I have thanks for helping new to winapi but not to figuring things out
There is a perfect example to do exactly what you want on MSDN here. The relevant code is copied below. As the introduction to the sample says
To determine which processes have loaded a particular DLL, you must enumerate the modules for each process. The following sample code uses the EnumProcessModules function to enumerate the modules of current processes in the system.
Now the sample code
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
int PrintModules( DWORD processID )
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
// Print the process identifier.
printf( "\nProcess ID: %u\n", processID );
// Get a handle to the process.
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, processID );
if (NULL == hProcess)
return 1;
// Get a list of all the modules in this process.
if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
TCHAR szModName[MAX_PATH];
// Get the full path to the module's file.
if ( GetModuleFileNameEx( hProcess, hMods[i], szModName,
sizeof(szModName) / sizeof(TCHAR)))
{
// Print the module name and handle value.
_tprintf( TEXT("\t%s (0x%08X)\n"), szModName, hMods[i] );
}
}
}
// Release the handle to the process.
CloseHandle( hProcess );
return 0;
}
int main( void )
{
DWORD aProcesses[1024];
DWORD cbNeeded;
DWORD cProcesses;
unsigned int i;
// Get the list of process identifiers.
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
return 1;
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the names of the modules for each process.
for ( i = 0; i < cProcesses; i++ )
{
PrintModules( aProcesses[i] );
}
return 0;
}
The only change you will need to make is to push-back the module names of interest to your std::vector<std::string> beforehand and then search that vector with the enumerated module names instead of printing them.
I have looked at the various topics relating to this, but couldn't find this specific issue I am having.
Things I looked at:
Injecting code into executable at runtime
C SIGSEGV Handler & Mprotect
Can I write-protect every page in the address space of a Linux process?
How to write a signal handler to catch SIGSEGV?
I am able to handle SIGSEGV gracefully when the protection needs to be set to either PROT_READ or PROT_WRITE in the handler. However, when I try to inject instructions with mmap, and then use mprotect to set it to PROT_READ only, and then I execute the instructions via inline assembly, it causes a SIGSEGV as intended, but the handler is unable to get the originating address causing the signal, so I am unable to mprotect it to PROT_READ | PROT_EXEC.
Example:
void sigHandler(int signum, siginfo_t *info, void *ptr) {
printf("Received signal number: %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
printf("SIGSEGV caused by this address: ? %p\n", info->si_addr);
char * alignedbaseAddr = (((unsigned int)(info->si_addr)) >> 12) * getPageSize();
printf("Aligning to %p\n", alignedbaseAddr);
//flip this page to be r+x
mprotect(alignedbaseAddr, getPageSize(), PROT_READ | PROT_EXEC);
}
void setupSignalHandler() {
action.sa_sigaction = sigHandler;
action.sa_flags = SA_SIGINFO;
sigemptyset(&action.sa_mask);
sigaction(SIGSEGV, &action, NULL);
}
int main(int argc, char *argv[]) {
char * baseAddr = (char*)mmap(NULL, getDiskSize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(baseAddr == MAP_FAILED) {
perror("Unable to mmap.");
}
printf("Process address space is %d\n", getDiskSize());
//no-op filler
for(int i = 0; i < (getDiskSize()) - 1; i++) {
baseAddr[i] = 0x90;
}
//ret instruction
baseAddr[i] = 0xc3;
if( mprotect(baseAddr, getDiskSize(), PROT_READ) == -1) {
perror("mprotect");
exit(1);
}
printf("Protecting addresses: %p to %p for READ_ONLY\n", baseAddr, baseAddr + getDiskSize() - 1);
setupSignalHandler();
__asm__
(
"call %%eax;"
: "=a" (output)
: "a" (baseAddr)
);
printf("Will this ever print?");
//close fd, and unmap memory
cleanUp();
return EXIT_SUCCESS;
}
Here is the resulting output:
Received signal number: 11
Signal originates from process 0
SIGSEGV caused by this address: ? (nil)
//the above output repeatedly loops, since it fails to "re mprotect" that page.
Architecture:
x86 32 bit
OS:
Ubuntu 11.04 - Linux version 2.6.38-12-generic (buildd#vernadsky) (gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) )
Any ideas? The above logic works fine for simply read and writing into memory. Is there
a better way to execute instructions at runtime as opposed to inline assembly?
Thanks in advance!
In that case, the faulting address is the instruction pointer. Cast your third argument ptr (of your signal handler installed with SA_SIGINFO) to a ucontext_t, and retrieve the appropriate register, perhaps as (untested code!)
ucontext_t *uc = ptr;
void* faultyip = uc->uc_mcontext.gregs[REG_IP];
Read carefully /usr/include/sys/ucontext.h for more.
I'm interested to know why you are asking!!