Jump to content
Tuts 4 You

Writing A Loader


.::God::.

Recommended Posts

Can someone give me an example in Delphi/ASM on how to write a loader:

That breaks on the first DefWindowProcA, modifies an address and then resumes process.

Just some example code will do, thanks.

;)

Link to comment

Here try something like this:

ProcessInfo								  PROCESS_INFORMATION <>
align dword
pContext CONTEXT <>
Patch db EBh, FEhOriginal dd ?
VAEntryPoint dd ?
VADefWindowProcA dd ?Invoke CreateProcess, _target,0,0,0,0,CREATE_SUSPENDED,0,0,0, offset ProcessInfo
Invoke WriteProcessMemory, ProcessInfo.hProcess, VAEntryPoint, offset Patch, 2, 0
Invoke ResumeThread, ProcessInfo.hThread.while TRUE
Invoke GetThreadContext, ProcessInfo.hThread, offset pContext
Push pContext.regEip
pop eax
.break .if eax == VAEntryPoint
.endwInvoke SuspendThread, ProcessInfo.hThread
Invoke WriteProcessMemory,ProcessInfo.hProcess, VAEntryPoint, offset Original, 2, 0
Invoke WriteProcessMemory, ProcessInfo.hProcess, VADefWindowProcA, offset Patch, 2, 0
Invoke ResumeThread, ProcessInfo.hThread.while TRUE
Invoke GetThreadContext, ProcessInfo.hThread, offset pContext
Push pContext.regEip
pop eax
.break .if eax == VADefWindowProcA
.endwInvoke SuspendThread, ProcessInfo.hThread
Invoke WriteProcessMemory,ProcessInfo.hProcess, VADefWindowProcA, offset Original, 2, 0
////////////////////////////////////////////////////////////////////////////////////////////////////////
Do your work
////////////////////////////////////////////////////////////////////////////////////////////////////////
Invoke ResumeThread, ProcessInfo.hThread
Invoke ExitProcess, 0

Something like that should work fine. Obviously this is not a complete example, you'll have to get original bytes and addresses, also mov pContext.ContextFlags, 1001Fh before GetThreadContext calls, otherwise it wont work.

Edited by What
Link to comment

Here is sample of how I do my loaders in delphi, Im still looking for my asm example and when i find it I will post it

const
{ Address's to write multi Patch1 and Patch2 }
MultiAddress1=$0054DCEB;
MultiAddress2=$0054DCF7; { Address to write Patch3 }
Address3=$004F47E9; { Address to write Patch4 }
Address4=$00539D44; { Address to write Patch5 }
Address5=$00463315;
{ Bytes to write }
MultiPatch1 : array[1..2] of byte = ($EB,$08);
MultiPatch2 : array[1..6] of byte = ($BB,$00,$00,$00,$00,$90);
Patch3 : array[1..6] of byte = ($90,$90,$90,$90,$90,$90);
Patch4 : array[1..2] of byte = ($EB,$20);
Patch5 : array[1..2] of byte = ($EB,$18);
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
{ Startup and variables used in procedure }
Path : String;
StartInfo : TStartupInfo;
ProcInfo : TProcessInformation;
CreateOK : Boolean;
Write: Cardinal;begin
Path:= 'C:\Myprogram.exe'
FillChar(StartInfo,SizeOf(TStartupInfo),#0);
FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
StartInfo.cb := SizeOf(TStartupInfo); CreateOK := CreateProcess(PChar(Path),nil, nil, nil,False,CREATE_SUSPENDED,nil, nil, StartInfo, ProcInfo); { check to see if successful }
if CreateOK then
begin{ ----------------------------------------------------------------------- }
{ Write Patch1 and Patch2 to memory }
WriteProcessMemory(ProcInfo.hProcess,ptr(MultiAddress1),@MultiPatch1,Length(MultiPalPatch1),Write);
WriteProcessMemory(ProcInfo.hProcess,ptr(MultiAddress2),@MultiPatch2,Length(MultiPalPatch2),Write); { Write Patch3 to memory }
WriteProcessMemory(ProcInfo.hProcess,ptr(Address3),@Patch3,Length(Patch3),Write); { Write Patch4 to memory }
WriteProcessMemory(ProcInfo.hProcess,ptr(Address4),@Patch4,Length(Patch4),Write); { Write Patch5 to memory }
WriteProcessMemory(ProcInfo.hProcess,ptr(Address5),@Patch5,Length(Patch5),Write);
{ ----------------------------------------------------------------------- }
{ Resume the thread }
ResumeThread(ProcInfo.hThread);
CloseHandle(ProcInfo.hProcess);
end;
end;

Thats for delphi using 5 diffrent patches and address's , Ill post asm code to do the exact same thing when i find it,

Edited by Departure
Link to comment

I hope that help you B)

.386 
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib .data?
StartupInfo STARTUPINFO <>
ProcessInfo PROCESS_INFORMATION <>
BytesWritten dd ?.data
TargetName db "App.exe",0
ProcError db "Error starting target process.",0
WriteError db "Error writing to target process",0
PatchByte db ??h
PatchVA dd ??h; <=Virtual address.code
start:
invoke CreateProcess,addr TargetName,0,0,0,0,CREATE_SUSPENDED,0,0,addr StartupInfo,addr ProcessInfo
.if eax==0
invoke MessageBox,NULL,addr ProcError,NULL,MB_ICONERROR
.else
invoke WriteProcessMemory,ProcessInfo.hProcess,PatchVA,addr PatchByte,1,addr BytesWritten
.if BytesWritten!=1
invoke MessageBox,NULL,addr WriteError,NULL,MB_ICONERROR
invoke TerminateProcess,ProcessInfo.hProcess,0
.else
invoke ResumeThread,ProcessInfo.hThread
.endif
.endif
invoke ExitProcess,NULL
end start
Link to comment
Here try something like this:
ProcessInfo								  PROCESS_INFORMATION <>
align dword
pContext CONTEXT <>
Patch db EBh, FEhOriginal dd ?
VAEntryPoint dd ?
VADefWindowProcA dd ?Invoke CreateProcess, _target,0,0,0,0,CREATE_SUSPENDED,0,0,0, offset ProcessInfo
Invoke WriteProcessMemory, ProcessInfo.hProcess, VAEntryPoint, offset Patch, 2, 0
Invoke ResumeThread, ProcessInfo.hThread.while TRUE
Invoke GetThreadContext, ProcessInfo.hThread, offset pContext
Push pContext.regEip
pop eax
.break .if eax == VAEntryPoint
.endwInvoke SuspendThread, ProcessInfo.hThread
Invoke WriteProcessMemory,ProcessInfo.hProcess, VAEntryPoint, offset Original, 2, 0
Invoke WriteProcessMemory, ProcessInfo.hProcess, VADefWindowProcA, offset Patch, 2, 0
Invoke ResumeThread, ProcessInfo.hThread.while TRUE
Invoke GetThreadContext, ProcessInfo.hThread, offset pContext
Push pContext.regEip
pop eax
.break .if eax == VADefWindowProcA
.endwInvoke SuspendThread, ProcessInfo.hThread
Invoke WriteProcessMemory,ProcessInfo.hProcess, VADefWindowProcA, offset Original, 2, 0
////////////////////////////////////////////////////////////////////////////////////////////////////////
Do your work
////////////////////////////////////////////////////////////////////////////////////////////////////////
Invoke ResumeThread, ProcessInfo.hThread
Invoke ExitProcess, 0

Something like that should work fine. Obviously this is not a complete example, you'll have to get original bytes and addresses, also mov pContext.ContextFlags, 1001Fh before GetThreadContext calls, otherwise it wont work.

Thx for that, i'll try it out now.

Link to comment

Whats not working about the examples?? Bothe asm look correct its just a matter of filling in the blanks to suit your app, And the Delphi one is straight from one of my own loaders So its just a matter of changing the Virtual Address's and Bytes, These codes should work fine for you the only other option if you still can get it to work is tell us the Virtual address's and the bytes you want changed and ofcause app path

Link to comment
  • 2 months later...
; Use: ml /c /coff loader.asm
; link /SUBSYSTEM:WINDOWS loader.obj rsrc.obj
; *** Begin of loader - Optimized for MASM32 ***.386
.model flat,stdcall
option casemap:noneinclude c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.libDlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD.dataAppName db 'MemoryPatcher',0
msg_run db 'Faild to launch program',0Dh,0Ah,'or CreateProcess function error :P ...',0
msg_read db 'ReadProcessMemory error ...',0
msg_ver db 'Wrong version :P ...',0
msg_cap db 'Memory Patcher error ...',0
msg_write db 'WriteProcessMemory error ...',0
m_progname db 'example.exe',0
; ---- Patch Data ----
m_addr_to_patch1 dd 0040FA77h
m_original_bytes1 db 07Ch, 01Eh
m_new_bytes1 db 0EBh, 01Eh
m_num_of_bytes1 dd 2DlgName db "SPLASH",0
TimerID dd 0
TimeOutValue dd 3000m_loop_me dd 10000.data?hInstance HINSTANCE ?
read_buffer db 512 dup (?)
startinfo STARTUPINFO <>
pi PROCESS_INFORMATION <>.code
start:invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,addr DlgName,NULL,addr DlgProc,NULLinvoke GetStartupInfo,addr startinfo
invoke CreateProcess,addr m_progname,NULL,NULL,NULL,FALSE,20h,NULL,NULL,addr startinfo,addr pi
test eax,eax
jz _launch_errormov ebx,m_loop_me_the_loop:
invoke ReadProcessMemory,dword ptr [pi],m_addr_to_patch1,addr read_buffer,m_num_of_bytes1,0
test eax,eax
jz _read_proc_errorlea esi,read_buffer
lea edi,m_original_bytes1
mov ecx,m_num_of_bytes1
repz cmpsb
jnz _down
jmp _patch_the_mother
_down:
dec ebx
jnz _the_loop
jmp _wrong_ver_patch_the_mother:
invoke WriteProcessMemory,dword ptr [pi],m_addr_to_patch1,addr m_new_bytes1,m_num_of_bytes1,0
test eax,eax
jz _write_proc_errorjmp _exit_launch_error:
invoke MessageBox,NULL,addr msg_run,addr msg_cap,MB_ICONSTOP+MB_OK
jmp _exit_read_proc_error:
invoke MessageBox,NULL,addr msg_read,addr msg_cap,MB_ICONSTOP+MB_OK
jmp _exit_wrong_ver:
invoke MessageBox,NULL,addr msg_ver,addr msg_cap,MB_ICONSTOP+MB_OK
jmp _exit_write_proc_error:
invoke MessageBox,NULL,addr msg_write,addr msg_cap,MB_ICONSTOP+MB_OK_exit:
invoke CloseHandle,dword ptr [pi]
invoke CloseHandle,dword ptr [startinfo]
invoke ExitProcess,0DlgProc proc uses esi edi ebx,hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .IF uMsg==WM_INITDIALOG
invoke SetTimer,hWnd,1,TimeOutValue,NULL
mov TimerID,eax
.ELSEIF uMsg==WM_TIMER
invoke KillTimer,hWnd,TimerID
invoke SendMessage,hWnd,WM_CLOSE,NULL,NULL
.ELSEIF uMsg==WM_CLOSE
invoke EndDialog,hWnd,NULL
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endpend start
.586
.model flat,stdcall
option casemap:noneinclude \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib.data
FileName db "example.exe",0
Error db "Process could not started!",0Startup STARTUPINFO <>
processinfo PROCESS_INFORMATION <>.data?
hInstance HINSTANCE ?
ByteBuf dd ?
.code
start:
invoke GetModuleHandleA, NULL
mov hInstance,eax
invoke CreateProcess, addr FileName, NULL, NULL, NULL, NULL, CREATE_SUSPENDED,NULL, NULL, addr Startup, addr processinfo
.if eax == NULL
invoke MessageBox, NULL, addr Error, NULL, MB_ICONEXCLAMATION
.else
call patch
.endif
invoke ExitProcess,eaxpatch proc hWnd: DWORD
LOCAL tmp: byte
_patch macro _pos, _byte
mov tmp, _byte
invoke WriteProcessMemory, processinfo.hProcess, _pos, addr tmp, 1, ByteBuf
invoke ResumeThread, processinfo.hThread
endm_patch 00543210h, 090h
_patch 00543211h, 090h
_patch 00543212h, 090h
_patch 00543213h, 090h
_patch 00543214h, 090h
_patch 00543215h, 090h
_patch 00543216h, 090h retpatch endpend start
program loader;uses
Windows;var
si : Startupinfo;
pi : Process_Information;procedure Patch(Address: Cardinal; PatchedBytes: Array Of Byte; OrigBytes: Array Of Byte);
var
NBW: Cardinal;
Old: byte;
begin
ReadProcessMemory(pi.hProcess, Pointer(Address), @Old, 1, NBW);
if OrigBytes[0] = Old then
begin
WriteProcessMemory(pi.hProcess, Pointer(Address), @PatchedBytes[0], Length(PatchedBytes), NBW);
ResumeThread(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
end
else
begin
Messagebox(0,pchar('Bytes not found...'),pchar('Error'),mb_iconinformation);
TerminateProcess(pi.hProcess,0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
end;
end;begin if CreateProcess(nil,'example.exe',nil,nil,FALSE, Create_Suspended,nil,nil,si,pi) = true then
begin
Patch($00543210, [$EB, $10], [$75, $10]);
Patch($00555555, [$C3, $90], [$55, $8B]);
end;
end.
Edited by KuNgBiM
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...