Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi DLL Injection Code Port Question (https://www.delphipraxis.net/117617-dll-injection-code-port-question.html)

_jaromir_ 22. Jul 2008 07:19


DLL Injection Code Port Question
 
Hallo,
I need to port the following code to delphi 7. So far it constantly crashes the target process, what do I need to do to fix? Please help.

Original code is here:
Zitat:

#define DLL_NAME "injected.dll"

__declspec(naked) loadDll(void)
{
_asm{
// Placeholder for the return address
push 0xDEADBEEF

// Save the flags and registers
pushfd
pushad

// Placeholder for the string address and LoadLibrary
push 0xDEADBEEF
mov eax, 0xDEADBEEF

// Call LoadLibrary with the string parameter
call eax

// Restore the registers and flags
popad
popfd

// Return control to the hijacked thread
ret
}
}

__declspec(naked) loadDll_end(void)
{
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
void *dllString;
void *stub;
unsigned long wowID, threadID, stubLen, oldIP, oldprot, loadLibAddy;
HANDLE hProcess, hThread;
CONTEXT ctx;

stubLen = (unsigned long)loadDll_end - (unsigned long)loadDll;

loadLibAddy = (unsigned long)GetProcAddress(GetModuleHandle("kernel32.dll" ), "LoadLibraryA");

wowID = GetTargetProcessIdFromProcname(PROC_NAME);
hProcess = OpenProcess((PROCESS_VM_WRITE | PROCESS_VM_OPERATION), false, wowID);

dllString = VirtualAllocEx(hProcess, NULL, (strlen(DLL_NAME) + 1), MEM_COMMIT, PAGE_READWRITE);
stub = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, dllString, DLL_NAME, strlen(DLL_NAME), NULL);

threadID = GetTargetThreadIdFromProcname(PROC_NAME);
hThread = OpenThread((THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME), false, threadID);
SuspendThread(hThread);

ctx.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(hThread, &ctx);
oldIP = ctx.Eip;
ctx.Eip = (DWORD)stub;
ctx.ContextFlags = CONTEXT_CONTROL;

VirtualProtect(loadDll, stubLen, PAGE_EXECUTE_READWRITE, &oldprot);
memcpy((void *)((unsigned long)loadDll + 1), &oldIP, 4);
memcpy((void *)((unsigned long)loadDll + 8 ), &dllString, 4);
memcpy((void *)((unsigned long)loadDll + 13), &loadLibAddy, 4);

WriteProcessMemory(hProcess, stub, loadDll, stubLen, NULL);
SetThreadContext(hThread, &ctx);

ResumeThread(hThread);

Sleep(8000);

VirtualFreeEx(hProcess, dllString, strlen(DLL_NAME), MEM_DECOMMIT);
VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT);
CloseHandle(hProcess);
CloseHandle(hThread);

return 0;
}
Here is my code but it is broken.

Delphi-Quellcode:
function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): DWORD; stdcall;
external 'kernel32.dll';

const
 THREAD_GET_CONTEXT = $0008;
 THREAD_SET_CONTEXT = $0010;
 THREAD_SUSPEND_RESUME = $0002;

procedure loadDll; assembler;
asm
      push $DEADBEEF // EIP
      pushfd
      pushad
      push $DEADBEEF // memory with dll name
      mov eax, $DEADBEEF // loadlibrary address
      call eax
      popad
      popfd
      ret
end;

procedure dEnd; assembler;
asm

end;

procedure InjectLib(const PID, TID: DWORD; DLL_NAME: PChar);
var
   stub, dllString: Pointer;
  stubLen, oldIP, oldprot, loadLibAddy, ret: DWORD;
  hProcess, hThread: THandle;
  ctx: CONTEXT;
  begin
   stubLen := DWORD(@dEnd) - DWORD(@loadDll);

   loadLibAddy := DWORD(GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA'));

   hProcess := OpenProcess(PROCESS_VM_WRITE or PROCESS_VM_OPERATION, False, PID);

   dllString := VirtualAllocEx(hProcess, nil, (lstrlen(DLL_NAME)+1), MEM_COMMIT, PAGE_READWRITE);
   stub     := VirtualAllocEx(hProcess, nil, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   WriteProcessMemory(hProcess, dllString, DLL_NAME, lstrlen(DLL_NAME), ret);

   hThread  := OpenThread(THREAD_GET_CONTEXT or THREAD_SET_CONTEXT or THREAD_SUSPEND_RESUME, false, TID);
   SuspendThread(hThread);

   ZeroMemory(@ctx, sizeof(ctx));

   ctx.ContextFlags := CONTEXT_CONTROL;
   GetThreadContext(hThread, ctx);
   oldIP  := ctx.Eip;
   ctx.Eip := DWORD(stub);
   ctx.ContextFlags := CONTEXT_CONTROL;

   VirtualProtect(@loadDll, stubLen, PAGE_EXECUTE_READWRITE, @oldprot);

   CopyMemory(pointer(dword(@loaddll) + 1), @oldIP, 4);
   CopyMemory(pointer(dword(@loaddll) + 8), dllString, 4);
   CopyMemory(pointer(dword(@loaddll) + 13), @loadLibAddy, 4);

   WriteProcessMemory(hProcess, stub, @loaddll, stubLen, ret);

   SetThreadContext(hThread, ctx);

   ResumeThread(hThread);

   Sleep(8000);

   VirtualFreeEx(hProcess, dllString, strlen(DLL_NAME), MEM_DECOMMIT);
   VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT);
   CloseHandle(hProcess);
   CloseHandle(hThread);
end;

nicodex 22. Jul 2008 07:51

Re: DLL Injection Code Port Question
 
Code:
ResumeThread(hThread);
Sleep(8000);
This is bad design, use WaitForSingleObject.
Thread Context Hijacking is unsafe, you should use "ready-to-use-and-working-due-to-years-of-research-and-testing" libraries for this purpose (e.g. http://www.madshi.net ).

_jaromir_ 22. Jul 2008 07:59

Re: DLL Injection Code Port Question
 
Nicodex
I understand this and you are right but I have to know why the example in c is not working in delphi? I do not care about reliability as it is for my code porting knowledge, not for use in applications for users. I just want to make it work as the c example, any help please? I believe the loadDll part is problem maybe, everything else seems ok from my view.

nicodex 22. Jul 2008 08:15

Re: DLL Injection Code Port Question
 
Zitat:

Zitat von _jaromir_
I believe the loadDll part is problem maybe, everything else seems ok from my view.

Currently I do not have the time to verify the whole code, sorry.

You are right about loadDll. Make sure / verify that the Delphi compiler does not generate stack frame code for the function (set a breakpoint on the "asm" statement of the function and take look at the CPU window.
For sanity reasons you might want to use a hand-crafted packed record with the target code.

brechi 22. Jul 2008 17:36

Re: DLL Injection Code Port Question
 
copymemory..(@dllstring)

_jaromir_ 22. Jul 2008 23:35

Re: DLL Injection Code Port Question
 
Hallo Brechi,
Even after change still same result and crash target process. I updated the code entirely and it still doing this! :pale: :wall: I will post updated code using packed record of assembly.

_jaromir_ 22. Jul 2008 23:48

Re: DLL Injection Code Port Question
 
Delphi-Quellcode:

type injt = packed record
 PushCommand: Byte; // 0x68
 PushEIP: DWORD; // Old EIP value from context to return to
 PushFd: Byte; // 0x9c
 PushAd: Byte; //0x60
 PushCommand2: Byte; // 0x68
 PushDLLName: DWORD; // address of LibraryName
 Call: Word; // 15ff
 CallAddr: DWORD; //LoadLibraryA address
 PopAd: Byte; // 0x61
 PopFd: Byte; // 0x9d
 Ret: Byte; // 0xc3
 AddrLoadLibrary: DWORD;
 LibraryName: array [0..MAX_PATH] of char;
 end;

procedure InjectLib(const PID, TID: DWORD);
var
  stubLen, oldIP, ret: DWORD;
  hProcess, hThread: THandle;
  ctx: CONTEXT;
    n: injt;
 stub: Pointer;
  begin

   stubLen := sizeof(n);

   hProcess := OpenProcess(PROCESS_VM_WRITE or PROCESS_VM_OPERATION, False, PID);

   if hProcess = 0 then exit;

   stub := VirtualAllocEx(hProcess, nil, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

   hThread := OpenThread(THREAD_GET_CONTEXT or THREAD_SET_CONTEXT or THREAD_SUSPEND_RESUME, false, TID);

   if hThread = 0 then exit;

   SuspendThread(hThread);

   ZeroMemory(@ctx, sizeof(ctx));

   ctx.ContextFlags := CONTEXT_CONTROL;
   GetThreadContext(hThread, ctx);
   oldIP  := ctx.Eip;
   ctx.Eip := DWORD(stub);
   ctx.ContextFlags := CONTEXT_CONTROL;


 with n do
 begin
 PushCommand := $68;
 PushEIP := oldIP;
 pushfd := $9c;
 pushad := $60 ;
 PushCommand2 := $68;
 PushDLLName := DWORD(stub) + 25;
 call := $15FF;
 calladdr := DWORD(stub) + 21;
 PopAd := $61;
 PopFd := $9d;
 ret := $c3;
 StrPCopy(@LibraryName, 'psapi.dll');
 AddrLoadLibrary := DWORD(GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA'));
end;

   WriteProcessMemory(hProcess, stub, @n, stubLen, ret);

   SetThreadContext(hThread, ctx);

   ResumeThread(hThread);

   WaitForSingleObject(hThread, INFINITE);

   VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT);
   CloseHandle(hProcess);
   CloseHandle(hThread);
end;
Still crashes target process =(. I think the error is somewhere else and maybe in context set?

brechi 23. Jul 2008 07:51

Re: DLL Injection Code Port Question
 
The old code was working for me with my changes i posted above.

Do an int3 at the beginning of the injected code and debug with a just in time debugger (ex. ollydbg).

Be sure you dont inject to fast afher target process start. Dllmain must be executed (if you create the process yourself with CREATE_SUSPENDED, its pauses at system breakpoint not dllmain).

Be Sure the Thread is stopped. Suspend Thread suspends the Thread only if the Result value is -1 or 0. Its like a counter. If someone calls Resumethread mroe times on the threadid it is increased. You have to call SuspendThread until its really suspended!

There are also some more bugs with this method


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:36 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz