1. 什么是重定位
本来每个进程都各自的进程地址空间, 但如果使用了比如注入技术后, 自身的那段代码就会进入到别人的进程地址空间内, 这将导致内部使用的API地址和变量地址发生变化, 因为注入到的位置和自身在自己进程地址空间种的基址很可能会不一样。
2. 如何解决重定位问题
使用汇编语言可以很好的解决重定位问题, 下面来看这段代码:
call $+5 ;机器码实际上是 E8 xx xx xx xx,一共5个字节
;$是但当前指令所在的地址,$+5就是越过当前指令
;获取下一条指令也就是pop ebx的地址并压入堆栈
pop ebx ;把pop ebx指令所在的地址[由call压入]弹出到ebx中
还有一段等价代码
call NEXT
NEXT:
pop ebx
上面两端代码的含义是一样的, 都是为了获取当前进程空间种当前指令的动态地址
3. 实例
下面这个实例使用了远线程注入方式, 把一段重定位过的汇编代码注入到了目标进程
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM
.const
IDD_DIALOG equ 101
IDC_EDT_BROWSE equ 1001
IDC_BTN_BROWSE equ 1002
IDC_BTN_INJECT equ 1003
IDC_STATIC_STATUS equ 1004
IDC_EDT_PID equ 1005
IDC_STATIC_PID equ 1006
.data?
hInstance dd ?
.data
g_strProcessName db MAX_PATH dup(0)
g_ddShellcodeSize dd offset INJECT_CODE_END - offset INJECT_CODE
g_szUser32 db "user32.dll", 0
g_szMsgBox db "MessageBoxA", 0
g_szOk db "状态: 成功", 0
g_szFail db "状态: 失败", 0
.code
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_DIALOG,NULL,addr DlgProc,NULL
invoke ExitProcess,0
; ofst = new - origin
; NewMsgBox = OldMsgBox + ofst
INJECT_CODE:
jmp STARTINJ
g_szMsgData db "你快乐了吗?", 0
g_szMsgCaption db "哈哈", 0
g_pfnMessageBoxA dd 0
STARTINJ:
; 进行重定位, 获取偏移
call NEXT
NEXT:
pop ebx
sub ebx, offset NEXT
push MB_OK
; 对MessageBoxA的标题进行重定位
mov eax, offset g_szMsgCaption
add eax, ebx
push eax
; 对MessageBoxA的内容进行重定位
mov eax, offset g_szMsgData
add eax, ebx
push eax
push NULL
; 对MessageBoxA进行重定位
mov eax, offset g_pfnMessageBoxA
add eax, ebx
call dword ptr [eax]
ret
INJECT_CODE_END:
GetPidByProcessName PROC stdcall hWnd:HWND
LOCAL @hSnapshot:HANDLE
LOCAL @stPe:PROCESSENTRY32
LOCAL @dwPid:DWORD
; 初始化局部变量
mov @dwPid, 0
mov @hSnapshot, INVALID_HANDLE_VALUE
; 获取目标进程名
invoke GetDlgItemText, hWnd, IDC_EDT_PID, offset g_strProcessName, size g_strProcessName
; 创建快照句柄
invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS, 0
mov @hSnapshot, eax
cmp eax, INVALID_HANDLE_VALUE
je CLEARSTUFF
; 遍历进程
mov @stPe.dwSize, size PROCESSENTRY32
invoke Process32First, @hSnapshot, addr @stPe
test eax, eax
jz CLEARSTUFF
GETPIDLOOP:
invoke lstrcmp, addr @stPe.szExeFile, addr g_strProcessName
jz GETPIDOKAY
invoke RtlZeroMemory, addr @stPe, size PROCESSENTRY32
mov @stPe.dwSize, size PROCESSENTRY32
invoke Process32Next, @hSnapshot, addr @stPe
test eax, eax
jnz GETPIDLOOP
jmp CLEARSTUFF
GETPIDOKAY:
mov eax, @stPe.th32ProcessID
mov @dwPid, eax
CLEARSTUFF:
cmp @hSnapshot, INVALID_HANDLE_VALUE
jz ENDING
invoke CloseHandle, @hSnapshot
mov @hSnapshot, INVALID_HANDLE_VALUE
ENDING:
mov eax, @dwPid
ret
GetPidByProcessName endp
InjectObject PROC stdcall hWin:HWND
LOCAL @hProcess:HANDLE
LOCAL @dwPid:DWORD
LOCAL @pShellcode:PBYTE
LOCAL @dwWritten:DWORD
LOCAL @hRemoteThread:DWORD
LOCAL @dwOldProtect:DWORD
; 初始化局部变量
mov @hRemoteThread, 0
mov @hProcess, NULL
mov @pShellcode, NULL
mov @dwWritten, 0
mov @dwPid, 0
; 获取MessageBoxA的地址
invoke VirtualProtect, INJECT_CODE, 64, PAGE_EXECUTE_READWRITE, addr @dwOldProtect
invoke GetModuleHandle, offset g_szUser32
invoke GetProcAddress, eax, offset g_szMsgBox
mov g_pfnMessageBoxA, eax
invoke VirtualProtect, INJECT_CODE, 64, addr @dwOldProtect, addr @dwOldProtect
; 获取目标进程PID
invoke GetDlgItemInt, hWin, IDC_EDT_PID, FALSE, FALSE
mov @dwPid, eax
test eax, eax
jz ENDFUNC
; 打开目标进程
invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, @dwPid
mov @hProcess, eax
test eax, eax
jz ENDFUNC
; 在目标进程内分配空间
invoke VirtualAllocEx, @hProcess, NULL, g_ddShellcodeSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE
mov @pShellcode, eax
test eax, eax
jz ENDFUNC
; 把shellcode写入目标进程
invoke WriteProcessMemory, @hProcess, @pShellcode, INJECT_CODE, g_ddShellcodeSize, addr @dwWritten
test eax, eax
jz ENDFUNC
; 创建远程线程
invoke CreateRemoteThread, @hProcess, NULL, 0, @pShellcode, NULL, 0, NULL
mov @hRemoteThread, eax
test eax, eax
jz ENDFUNC
invoke Sleep, 500
ENDFUNC:
cmp @hRemoteThread, 0
jz @F
invoke CloseHandle, @hRemoteThread
mov @hRemoteThread, 0
@@:
cmp @hProcess, 0
jz @F
invoke CloseHandle, @hProcess
mov @hProcess, 0
@@:
ret
InjectObject endp
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
.elseif eax==WM_COMMAND
mov eax, wParam
cmp ax, IDC_BTN_BROWSE
jnz @F
; 获取目标进程PID
invoke GetPidByProcessName, hWin
invoke SetDlgItemInt, hWin, IDC_EDT_PID, eax, FALSE
test eax, eax
jz NOEXEC
mov eax, TRUE
ret
@@:
cmp ax, IDC_BTN_INJECT
jnz NOEXEC
invoke InjectObject, hWin
test eax, eax
jz NOEXEC
invoke SetDlgItemText, hWin, IDC_STATIC_STATUS, offset g_szOk
mov eax, TRUE
ret
NOEXEC:
invoke SetDlgItemText, hWin, IDC_STATIC_STATUS, offset g_szFail
mov eax, FALSE
ret
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
运行如下:
(完)