I'm trying to call a function in my dll.
the DLL is injected into ANOTHER PROCESS so i need to be able to call the exported function after it's been injected into a target process.
my exported function looks like this:
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
EXTERN_DLL_EXPORT void InjectPacketToServer(unsigned char *packet, int length)
{
int value;
int senderoffset = 0x0075F8D8;
__asm
{
mov eax, senderoffset
mov value, eax
}
memcpy((void*)SEND_CODE_CAVE, (void*)packet, length);
int SenderID = *(int*)value;
int PacketLength = length;
int Send = 0x00577A90;
__asm
{
mov edx, PacketLength
push edx
mov eax, SEND_CODE_CAVE
push eax
mov ecx, [SenderID]
call Send
}
}
I am trying to call it like this:
#include <Windows.h>
typedef int (*InjectPacketToServer)(unsigned char *packet, int length);
InjectPacketToServer Inject;
BYTE packet[3] = { 0x13, 0x01, 0x01};
int length = 3;
int main()
{
HRESULT ret;
HMODULE pModule;
pModule = LoadLibrary("baram.dll");
ret = GetLastError();
Inject = (InjectPacketToServer)GetProcAddress(pModule, "InjectPacketToServer");
ret = GetLastError();
Inject(packet, length);
return ret;
}
I'm getting errors:
ret 0x000003e6 : Invalid access to memory location. HRESULT
on this line:
pModule = LoadLibrary("baram.dll");
can somebody Please tell me what I'm doing wrong here?
help appreciated!
Did you google?
MS support says the cause is:
The Windows NT status code STATUS_ACCESS_VIOLATION is mapped to the Win32 error code ERROR_NOACCESS. As a result, if the operating system loader encounters an access violation (exception C0000005) while mapping the specified DLL file image or executing the startup code, the loader will set the last error to 998 (ERROR_NOACCESS) and the LoadLibrary() function will fail with a return value of NULL.
and you should
To troubleshoot the LoadLibrary() failure, run the application under a debugger and enable first chance exception handling for the C0000005 Access Violation exception. If an access violation occurs when the LoadLibrary() function is called, the application will break into the debugger. The debugger's call stack can then be used to trace where the exception occurred. The stack trace should help you narrow down the actual problem related to the exception being encountered.
Related
I have the following code:
#include <windows.h>
#include <minidumpapiset.h>
#include <strsafe.h>
#include <fileapi.h>
#include <iostream>
#include <signal.h>
#include <minwinbase.h>
#include <new.h>
#include "StackWalker.h"
int minidumpId = 0;
#ifndef _AddressOfReturnAddress
// Taken from: http://msdn.microsoft.com/en-us/library/s975zw7k(VS.71).aspx
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
// _ReturnAddress and _AddressOfReturnAddress should be prototyped before use
EXTERNC void* _AddressOfReturnAddress(void);
EXTERNC void* _ReturnAddress(void);
EXTERNC int __cdecl _purecall();
#endif
EXCEPTION_POINTERS ExceptionPointers;
EXCEPTION_RECORD ExceptionRecord;
CONTEXT ContextRecord;
void GetExceptionPointers(DWORD exceptionCode, EXCEPTION_POINTERS** exceptionPointers)
{
// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
ZeroMemory(&ExceptionPointers, sizeof(EXCEPTION_POINTERS));
ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
ZeroMemory(&ContextRecord, sizeof(CONTEXT));
// Looks like a workaround for some bug in RtlCaptureContext. But no description.
#ifdef _X86_
__asm {
mov dword ptr[ContextRecord.Eax], eax
mov dword ptr[ContextRecord.Ecx], ecx
mov dword ptr[ContextRecord.Edx], edx
mov dword ptr[ContextRecord.Ebx], ebx
mov dword ptr[ContextRecord.Esi], esi
mov dword ptr[ContextRecord.Edi], edi
mov word ptr[ContextRecord.SegSs], ss
mov word ptr[ContextRecord.SegCs], cs
mov word ptr[ContextRecord.SegDs], ds
mov word ptr[ContextRecord.SegEs], es
mov word ptr[ContextRecord.SegFs], fs
mov word ptr[ContextRecord.SegGs], gs
pushfd
pop[ContextRecord.EFlags]
}
ContextRecord.ContextFlags = CONTEXT_CONTROL;
#pragma warning(push)
#pragma warning(disable : 4311)
ContextRecord.Eip = (ULONG)_ReturnAddress();
ContextRecord.Esp = (ULONG)_AddressOfReturnAddress();
#pragma warning(pop)
ContextRecord.Ebp = *(static_cast<ULONG*>(_AddressOfReturnAddress()) - 1);
#elif defined(_IA64_) || defined(_AMD64_) || defined(_ARM_) || defined(_ARM64_)
CaptureContext(&ContextRecord);
#else /* defined (_IA64_) || defined (_AMD64_) || defined(_ARM_) || defined(_ARM64_) */
ZeroMemory(&ContextRecord, sizeof(ContextRecord));
#endif /* defined (_IA64_) || defined (_AMD64_) || defined(_ARM_) || defined(_ARM64_) */
ExceptionRecord.ExceptionCode = exceptionCode;
ExceptionRecord.ExceptionAddress = _ReturnAddress();
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
*exceptionPointers = &ExceptionPointers;
(*exceptionPointers)->ExceptionRecord = &ExceptionRecord;
(*exceptionPointers)->ContextRecord = &ContextRecord;
}
class DbgLibrary final
{
public:
DbgLibrary()
{
dbgLibrary = LoadLibraryW(L"dbghelp.dll");
}
~DbgLibrary()
{
FreeLibrary(dbgLibrary);
}
explicit operator bool() const
{
return dbgLibrary != NULL;
}
bool WriteMinidump(HANDLE file, EXCEPTION_POINTERS* exceptionPointers) const
{
MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
exceptionInformation.ThreadId = GetCurrentThreadId();
exceptionInformation.ExceptionPointers = exceptionPointers;
exceptionInformation.ClientPointers = FALSE;
MINIDUMP_CALLBACK_INFORMATION callbackInformation;
callbackInformation.CallbackRoutine = NULL;
callbackInformation.CallbackParam = NULL;
typedef BOOL(WINAPI* LPMINIDUMPWRITEDUMP)(HANDLE processHandle, DWORD ProcessId, HANDLE fileHandle,
MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserEncoderParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
LPMINIDUMPWRITEDUMP pfnMiniDumpWriteDump =
(LPMINIDUMPWRITEDUMP)GetProcAddress(dbgLibrary, "MiniDumpWriteDump");
if (NULL == pfnMiniDumpWriteDump)
{
return false;
}
BOOL isWriteSucceed = pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpNormal,
&exceptionInformation, NULL, &callbackInformation);
return isWriteSucceed;
}
private:
HMODULE dbgLibrary;
};
inline HANDLE CreateNativeFile(const wchar_t* filePath)
{
HANDLE file = NULL;
file = CreateFileW(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
return file;
}
void CreateMiniDump(PEXCEPTION_POINTERS exceptionPointers)
{
const DbgLibrary dbgLibrary;
if (dbgLibrary)
{
wchar_t FILE_PATH[4096];
// Write `exceptionPointers` to the minidump file
StringCbPrintfW(FILE_PATH, sizeof(FILE_PATH), L"%ls\\%ls_%ld.dmp", ".",
L"minidump", minidumpId++);
HANDLE hMinidump = CreateNativeFile(FILE_PATH);
if (hMinidump != INVALID_HANDLE_VALUE)
{
dbgLibrary.WriteMinidump(hMinidump, exceptionPointers);
CloseHandle(hMinidump);
}
}
}
LONG WINAPI SehHandler(PEXCEPTION_POINTERS exceptionPointers)
{
std::cerr << "SehHandler\n";
CreateMiniDump(exceptionPointers);
return EXCEPTION_EXECUTE_HANDLER;
}
void SigsegvHandler(int)
{
std::cerr << "SigsegvHandler\n";
PEXCEPTION_POINTERS exceptionPointers = static_cast<PEXCEPTION_POINTERS>(_pxcptinfoptrs);
// Write minidump file
CreateMiniDump(exceptionPointers);
}
int __cdecl NewHandler(size_t size)
{
std::cerr << "NewHandler\n";
// 'new' operator memory allocation exception
PEXCEPTION_POINTERS exceptionPointers;
GetExceptionPointers(STATUS_NO_MEMORY, &exceptionPointers);
CreateMiniDump(exceptionPointers);
return 0;
}
struct A5 {
void F()
{
while (true)
{
int* a = new int[50000000];
}
}
};
struct A4 {
A5 a;
void F()
{
a.F();
}
};
struct A3 {
A4 a;
void F()
{
a.F();
}
};
struct A2 {
A3 a;
void F()
{
a.F();
}
};
struct A1 {
A2 a;
void F()
{
a.F();
}
};
int main()
{
SetUnhandledExceptionFilter(SehHandler);
signal(SIGSEGV, SigsegvHandler);
_set_new_handler(NewHandler);
A1().F();
return 0;
}
Here two handlers would be invoked: NewHandler and SehHandler. The first one because of bad_alloc in operator new[], the second one because of unhandled exception. In both handlers I create minidump with information about crash.
NewHandler:
Thread 0 (crashed)
0 StackWalker_VC2017.exe!_callnewh [new_handler.cpp : 79 + 0x2]
eip = 0x0040a636 esp = 0x0019fefc ebp = 0x0019ff08 ebx = 0x00311000
esi = 0x00401d10 edi = 0x00655368 eax = 0x0042eed0 ecx = 0x00000000
edx = 0x00655368 efl = 0x00000202
Found by: given as instruction pointer in context
1 StackWalker_VC2017.exe!operator new(unsigned int) [new_scalar.cpp : 40 + 0x8]
eip = 0x00404a05 esp = 0x0019ff10 ebp = 0x0019ff14
Found by: call frame info
2 StackWalker_VC2017.exe!A5::F() [main.cpp : 197 + 0xa]
eip = 0x00401d0a esp = 0x0019ff1c ebp = 0x0019ff28
Found by: call frame info
3 StackWalker_VC2017.exe!main [main.cpp : 239 + 0x8]
eip = 0x00402500 esp = 0x0019ff24 ebp = 0x0019ff28
Found by: call frame info
4 StackWalker_VC2017.exe!static int __scrt_common_main_seh() [exe_common.inl : 288 + 0x1c]
eip = 0x00404c5d esp = 0x0019ff30 ebp = 0x0019ff70
Found by: call frame info
5 kernel32.dll + 0x1fa29
eip = 0x7712fa29 esp = 0x0019ff78 ebp = 0x0019ff80
Found by: call frame info
6 ntdll.dll + 0x67a9e
eip = 0x77c97a9e esp = 0x0019ff88 ebp = 0x0019ffdc
Found by: previous frame's frame pointer
7 ntdll.dll + 0x67a6e
eip = 0x77c97a6e esp = 0x0019ffe4 ebp = 0x0019ffec
Found by: previous frame's frame pointer
SehHandler:
Thread 0 (crashed)
0 KERNELBASE.dll + 0x12b812
eip = 0x76ddb812 esp = 0x0019fe68 ebp = 0x0019fec4 ebx = 0x19930520
esi = 0x00645a90 edi = 0x0042c754 eax = 0x0019fe68 ecx = 0x00000003
edx = 0x00000000 efl = 0x00000212
Found by: given as instruction pointer in context
1 StackWalker_VC2017.exe!_CxxThrowException [throw.cpp : 74 + 0x19]
eip = 0x00405a98 esp = 0x0019fecc ebp = 0x0019fef4
Found by: previous frame's frame pointer
2 StackWalker_VC2017.exe!__scrt_throw_std_bad_alloc() [throw_bad_alloc.cpp : 35 + 0x16]
eip = 0x0040509c esp = 0x0019fefc ebp = 0x0019ff10
Found by: call frame info
3 StackWalker_VC2017.exe!main [main.cpp : 239 + 0x8]
eip = 0x00402500 esp = 0x0019ff24 ebp = 0x0019ff14
Found by: call frame info with scanning
Extracted stacks using breakpad minidump_stackwalk:
The question is why SehHandler stacktrace does not have all function calls?
The main problem is that in project I use crash handlers for logging information in dumps. But creating minidump on each NewHandler call is not inappropriate solution, because sometimes bad_alloc could be fixed and exception thrown in try/catch block, that means that it is expected behaviour. So I want to handle bad_alloc in unhandled exception handler, so that it would definitely be crash. Also problem occurs only in release builds.
As mentioned in https://developercommunity.visualstudio.com/t/stdbad-alloc-failures-are-undebuggable/542559?viewtype=solutions it is bug in msvc. Unfortunately there is no good solution for release builds.
So, I tried to run my go code on C++ project with dynamic loading. It's working great, except there is some unwanted string on returned value. As I explained down, I got some information from Go that unwanted.
My go code:
package main
import "C"
func main() {}
//export GetTestString
func GetTestString() string {
return "test"
}
I build it with:
go build -buildmode=c-shared -o test.so test.go
Dynamically load it on my CPP project with this function:
typedef struct { const char *p; ptrdiff_t n; } GoString;
void getTestString() {
void *handle;
char *error;
handle = dlopen ("./test.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
// resolve getTestString symbol and assign to fn ptr
auto getTestString = (GoString (*)())dlsym(handle, "GetTestString");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
// call GetTestString()
GoString testString = (*getTestString)();
printf("%s\n", testString.p);
// close file handle when done
dlclose(handle);
}
Output is:
"testtrue ...\n H_T= H_a= H_g= MB, W_a= and cnt= h_a= h_g= h_t= max= ptr siz= tab= top= u_a= u_g=, ..., fp:argp=falsefaultgcingpanicsleepsse41sse42ssse3 (MB)\n addr= base code= ctxt: curg= goid jobs= list= m->p= next= p->m= prev= span= varp=(...)\n, not SCHED efenceerrno objectpopcntscvg: selectsweep (scan (scan) MB in dying= locks= m->g0= nmsys= s=nil\n, goid=, size=, sys: GODEBUGIO waitSignal \ttypes \tvalue=cs fs gctracegs panic: r10 r11 r12 r13 r14 r15 r8 r9 rax rbp rbx rcx rdi rdx rflags rip rsi rsp runningsignal syscallunknownwaiting etypes goalĪ= is not mcount= minutes nalloc= newval= nfree..."
When passing strings via pointer to C you need either use length (n) in GoString to fetch right number of characters as string at p is not \0 terminated. Or you can return *C.char instead of string and use C.CString() to allocate copy on C heap (which you then are responsible for freeing after use). See Cgo documentation here.
What is happening in your code is that printf() simply prints all characters starting from location pointed to by string.p until it hits \0 terminator - that's why you see contents of memory after test.
So you can do either something like:
printf("%.*s\n", testString.n, testString.p);
(but note that most functions that operate on C strings which are expected to be \0 terminated will not work on this pointer unless they also take length of string)
or change Go part to something like this and then free() pointer after use on C side:
func GetTestString() *C.char {
return C.CString("test") // CString will allocate string on C heap
}
I got a simple code and it gives me a compiler error for no reason
inline assembler syntax error in 'opcode'; found 'constant'
DWORD connectFunctionAddressReturn = 0x775368F7;
int __cdecl ws2_32_connect_hook_output(SOCKET s, const struct sockaddr *name, int namelen) {
struct sockaddr_in *in = (struct sockaddr_in *)connect_name;
printf("Attempting connect %d.%d.%d.%d : %d\n", in->sin_addr.S_un.S_un_b.s_b1, in->sin_addr.S_un.S_un_b.s_b2, in->sin_addr.S_un.S_un_b.s_b3, in->sin_addr.S_un.S_un_b.s_b4, htons(in->sin_port));
}
void __declspec(naked) ws2_32_connect_hook(void) { //ws2_32.connect = 775368F5
__asm {
PUSHAD //To be in safe environment
PUSHFD //To be safe environment
PUSH 0x10
PUSH DWORD PTR SS:[EBP+0x8]
PUSH DWORD PTR DS:[ESI+0x14]
CALL DWORD PTR ws2_32_connect_hook_output //<-- ERROR HERE
ADD ESP, 0xC //clean __cdecl,4,8,C
POPFD //Finish being in safe environment
POPAD //Finish being in safe environment
JMP connectFunctionAddressReturn // <-- ERROR HERE
}
}
solved it, I had CALL AND JMP defined so it errored in ASM code.
#define CALL 0xE8
#define JMP 0xE9
I'm trying to create a proxy dll for dinput8.dll. The .exe load my custom dll (proxy dll) dinput8.dll. dinput8_x86.dll is renamed version of the origin .dll that loaded by my proxy dll. Everything work fine, but when i remove the MessageBox code line, then rebuild the project, i have got the error:
Exception thrown at 0x772BBC61 in localhost_dinput8.exe: 0xC0000005:
Access violation reading location 0x00000250.
Unhandled exception at 0x772BBC61 in localhost_dinput8.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.
The exception throw out when trace over LoadLibrary(_T(".\\dinput8_x86.dll"));. I don't know why, can anyone help me please, i don't want to show that message box everytime my dll is loaded. If i put back the code line: MessageBox -> the exception is GONE.
Here is my example code of proxy DLL.
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#pragma pack(1)
FARPROC p[5] = { 0 };
extern "C" BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
{
static HINSTANCE hL;
if (reason == DLL_PROCESS_ATTACH)
{
hL = LoadLibrary(_T(".\\dinput8_x86.dll")); // The exception at here
if (!hL) return false;
p[0] = GetProcAddress(hL, "DllGetClassObject");
p[1] = GetProcAddress(hL, "DllCanUnloadNow");
p[2] = GetProcAddress(hL, "DirectInput8Create");
p[3] = GetProcAddress(hL, "DllRegisterServer");
p[4] = GetProcAddress(hL, "DllUnregisterServer");
//MessageBox(NULL,_T("Hello World"),_T("Hi"),NULL);//Exception gone when uncomment this line
}
if (reason == DLL_PROCESS_DETACH)
FreeLibrary(hL);
return TRUE;
}
extern "C" __declspec(naked) void Proxy_DllGetClassObject()
{
__asm
{
jmp p[0 * 4];
}
}
extern "C" __declspec(naked) void Proxy_DllCanUnloadNow()
{
__asm
{
jmp p[1 * 4];
}
}
extern "C" __declspec(naked) void Proxy_DirectInput8Create()
{
__asm
{
jmp p[2 * 4];
}
}
extern "C" __declspec(naked) void Proxy_DllRegisterServer()
{
__asm
{
jmp p[3 * 4];
}
}
extern "C" __declspec(naked) void Proxy_DllUnregisterServer()
{
__asm
{
jmp p[4 * 4];
}
}
Here is my definition file:
dinput8.def
EXPORTS
DllGetClassObject=Proxy_DllGetClassObject #1
DllCanUnloadNow=Proxy_DllCanUnloadNow #2
DirectInput8Create=Proxy_DirectInput8Create #3
DllRegisterServer=Proxy_DllRegisterServer #4
DllUnregisterServer=Proxy_DllUnregisterServer #5
Additional information:
Im using Win7 Professional x64 update full
Visual Studio 2015
Project build on win32 x86 profile
Edit:
I realize that if I replace MessageBox to any other API such as MessageBeep or ShowCursor which in WinUser.h, the exception not show anymore. But if i remove it, exception show up. I still don't know why?
From Dynamic-Link Library Best Practices:
You should never perform the following tasks from within DllMain:
Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.
I'm trying to create a proxy dinput8.dll to allow keyboard remapping in a game, and have pieced together some instructions etc to come up with the following :
#include <windows.h>
#include <strsafe.h>
#pragma pack(1)
HINSTANCE hLThis = 0;
HINSTANCE hL = 0;
FARPROC p[5] = {0};
BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) {
if (reason == DLL_PROCESS_ATTACH) {
hLThis = hInst;
hL = LoadLibrary("originaldinput8.dll");
if (!hL) return false;
p[0] = GetProcAddress(hL,"DllCanUnloadNow");
p[1] = GetProcAddress(hL,"DllGetClassObject");
p[2] = GetProcAddress(hL,"DllRegisterServer");
p[3] = GetProcAddress(hL,"DllUnregisterServer");
p[4] = GetProcAddress(hL,"DirectInput8Create");
} else if (reason == DLL_PROCESS_DETACH) {
FreeLibrary(hL);
}
return 1;
}
extern "C" __declspec(naked) void __stdcall __E__0__()
{
__asm
{
jmp p[4];
}
}
// DllCanUnloadNow
extern "C" __declspec(naked) void __stdcall __E__1__()
{
__asm
{
jmp p[0];
}
}
// DllGetClassObject
extern "C" __declspec(naked) void __stdcall __E__2__()
{
__asm
{
jmp p[1];
}
}
// DllRegisterServer
extern "C" __declspec(naked) void __stdcall __E__3__()
{
__asm
{
jmp p[2];
}
}
// DllUnregisterServer
extern "C" __declspec(naked) void __stdcall __E__4__()
{
__asm
{
jmp p[3];
}
}
The module definition file it links against is as follows :
EXPORTS
DirectInput8Create=__E__0__ #1
DllCanUnloadNow=__E__1__ #2
DllGetClassObject=__E__2__ #3
DllRegisterServer=__E__3__ #4
DllUnregisterServer=__E__4__ #5
The project builds fine and produces the DLL, which I then place alongside originaldinput8.dll (a renamed version of C:\Windows\SysWOW64\dinput8.dll) and run the game. But it immediately crashes - a debugger run produces the following error just as the call to LoadLibrary occurs.
First-chance exception at 0x75ed75f8 in th06e.exe: 0xC0000005: Access violation reading location 0x00000250.
*** An Access Violation occurred in "C:\Users\Username\Documents\Visual Studio 2010\Projects\dinput8\Debug\th06e.exe" :
The instruction at 00000000775A1221 tried to read from an invalid address, 0000000000000250
*** enter .exr 000000000008E030 for the exception record
*** enter .cxr 000000000008DB40 for the context
*** then kb to get the faulting stack
Unhandled exception at 0x75ed75f8 in th06e.exe: 0xC000041D: An unhandled exception was encountered during a user callback.
The program '[5704] th06e.exe: Native' has exited with code -1073740771 (0xc000041d).
This was previously working (after an issue where I was using the 64-bit original DLL instead of the 32-bit one) but somehow it has now stopped working and I'm not sure what the issue is.
I don't think it's an issue with it finding the DLL file - removing the DLL file or using the wrong one results in LoadLibrary failing without causing a crash, error code 193.
Any ideas?