在看Windows 32位汇编的时候,有一章是利用调试API脱壳,首先写了一个简单的exe,代码如下:
根据eax的值来显示消息框的简单程序,直接运行会输出错误的消息框。反汇编看看
一个很简单的程序,结构可以直接看出来.只需要改变00401004的值就可以让他显示正确的消息框
这时入口地址是00401000.需要修改的地址是
00401004
然后我把他用upx加壳。
加壳以后我们再反汇编看看
UPX1:00405120 start proc near
UPX1:00405120 pusha
UPX1:00405121 mov esi, offset dword_405000
UPX1:00405126 lea edi, [esi-4000h]
UPX1:0040512C push edi
UPX1:0040512D or ebp, 0FFFFFFFFh
UPX1:00405130 jmp short loc_405142
UPX1:00405130 ; ---------------------------------------------------------------------------
UPX1:00405132 align 8
UPX1:00405138
UPX1:00405138 loc_405138: ; CODE XREF: start:loc_405149j
UPX1:00405138 mov al, [esi]
UPX1:0040513A inc esi
UPX1:0040513B mov [edi], al
UPX1:0040513D inc edi
UPX1:0040513E
UPX1:0040513E loc_40513E: ; CODE XREF: start+B6j
UPX1:0040513E ; start+CDj
UPX1:0040513E add ebx, ebx
UPX1:00405140 jnz short loc_405149
UPX1:00405142
UPX1:00405142 loc_405142: ; CODE XREF: start+10j
UPX1:00405142 mov ebx, [esi]
UPX1:00405144 sub esi, 0FFFFFFFCh
UPX1:00405147 adc ebx, ebx
UPX1:00405149
UPX1:00405149 loc_405149: ; CODE XREF: start+20j
UPX1:00405149 jb short loc_405138
UPX1:0040514B mov eax, 1
UPX1:00405150
UPX1:00405150 loc_405150: ; CODE XREF: start+3Fj
UPX1:00405150 ; start+4Aj
UPX1:00405150 add ebx, ebx
UPX1:00405152 jnz short loc_40515B
UPX1:00405154 mov ebx, [esi]
UPX1:00405156 sub esi, 0FFFFFFFCh
UPX1:00405159 adc ebx, ebx
UPX1:0040515B
UPX1:0040515B loc_40515B: ; CODE XREF: start+32j
UPX1:0040515B adc eax, eax
UPX1:0040515D add ebx, ebx
UPX1:0040515F jnb short loc_405150
UPX1:00405161 jnz short loc_40516C
UPX1:00405163 mov ebx, [esi]
UPX1:00405165 sub esi, 0FFFFFFFCh
UPX1:00405168 adc ebx, ebx
UPX1:0040516A jnb short loc_405150
UPX1:0040516C
UPX1:0040516C loc_40516C: ; CODE XREF: start+41j
UPX1:0040516C xor ecx, ecx
UPX1:0040516E sub eax, 3
UPX1:00405171 jb short loc_405180
UPX1:00405173 shl eax, 8
UPX1:00405176 mov al, [esi]
UPX1:00405178 inc esi
UPX1:00405179 xor eax, 0FFFFFFFFh
UPX1:0040517C jz short loc_4051F2
UPX1:0040517E mov ebp, eax
UPX1:00405180
UPX1:00405180 loc_405180: ; CODE XREF: start+51j
UPX1:00405180 add ebx, ebx
UPX1:00405182 jnz short loc_40518B
UPX1:00405184 mov ebx, [esi]
UPX1:00405186 sub esi, 0FFFFFFFCh
UPX1:00405189 adc ebx, ebx
UPX1:0040518B
UPX1:0040518B loc_40518B: ; CODE XREF: start+62j
UPX1:0040518B adc ecx, ecx
UPX1:0040518D add ebx, ebx
UPX1:0040518F jnz short loc_405198
UPX1:00405191 mov ebx, [esi]
UPX1:00405193 sub esi, 0FFFFFFFCh
UPX1:00405196 adc ebx, ebx
UPX1:00405198
UPX1:00405198 loc_405198: ; CODE XREF: start+6Fj
UPX1:00405198 adc ecx, ecx
UPX1:0040519A jnz short loc_4051BC
UPX1:0040519C inc ecx
UPX1:0040519D
UPX1:0040519D loc_40519D: ; CODE XREF: start+8Cj
UPX1:0040519D ; start+97j
UPX1:0040519D add ebx, ebx
UPX1:0040519F jnz short loc_4051A8
UPX1:004051A1 mov ebx, [esi]
UPX1:004051A3 sub esi, 0FFFFFFFCh
UPX1:004051A6 adc ebx, ebx
UPX1:004051A8
UPX1:004051A8 loc_4051A8: ; CODE XREF: start+7Fj
UPX1:004051A8 adc ecx, ecx
UPX1:004051AA add ebx, ebx
UPX1:004051AC jnb short loc_40519D
UPX1:004051AE jnz short loc_4051B9
UPX1:004051B0 mov ebx, [esi]
UPX1:004051B2 sub esi, 0FFFFFFFCh
UPX1:004051B5 adc ebx, ebx
UPX1:004051B7 jnb short loc_40519D
UPX1:004051B9
UPX1:004051B9 loc_4051B9: ; CODE XREF: start+8Ej
UPX1:004051B9 add ecx, 2
UPX1:004051BC
UPX1:004051BC loc_4051BC: ; CODE XREF: start+7Aj
UPX1:004051BC cmp ebp, 0FFFFF300h
UPX1:004051C2 adc ecx, 1
UPX1:004051C5 lea edx, [edi+ebp]
UPX1:004051C8 cmp ebp, 0FFFFFFFCh
UPX1:004051CB jbe short loc_4051DC
UPX1:004051CD
UPX1:004051CD loc_4051CD: ; CODE XREF: start+B4j
UPX1:004051CD mov al, [edx]
UPX1:004051CF inc edx
UPX1:004051D0 mov [edi], al
UPX1:004051D2 inc edi
UPX1:004051D3 dec ecx
UPX1:004051D4 jnz short loc_4051CD
UPX1:004051D6 jmp loc_40513E
UPX1:004051D6 ; ---------------------------------------------------------------------------
UPX1:004051DB align 4
UPX1:004051DC
UPX1:004051DC loc_4051DC: ; CODE XREF: start+ABj
UPX1:004051DC ; start+C9j
UPX1:004051DC mov eax, [edx]
UPX1:004051DE add edx, 4
UPX1:004051E1 mov [edi], eax
UPX1:004051E3 add edi, 4
UPX1:004051E6 sub ecx, 4
UPX1:004051E9 ja short loc_4051DC
UPX1:004051EB add edi, ecx
UPX1:004051ED jmp loc_40513E
UPX1:004051F2 ; ---------------------------------------------------------------------------
UPX1:004051F2
UPX1:004051F2 loc_4051F2: ; CODE XREF: start+5Cj
UPX1:004051F2 pop esi
UPX1:004051F3 mov edi, esi
UPX1:004051F5 mov ecx, 3
UPX1:004051FA
UPX1:004051FA loc_4051FA: ; CODE XREF: start+E1j
UPX1:004051FA ; start+E6j
UPX1:004051FA mov al, [edi]
UPX1:004051FC inc edi
UPX1:004051FD sub al, 0E8h
UPX1:004051FF
UPX1:004051FF loc_4051FF: ; CODE XREF: start+104j
UPX1:004051FF cmp al, 1
UPX1:00405201 ja short loc_4051FA
UPX1:00405203 cmp byte ptr [edi], 0
UPX1:00405206 jnz short loc_4051FA
UPX1:00405208 mov eax, [edi]
UPX1:0040520A mov bl, [edi+4]
UPX1:0040520D shr ax, 8
UPX1:00405211 rol eax, 10h
UPX1:00405214 xchg al, ah
UPX1:00405216 sub eax, edi
UPX1:00405218 sub bl, 0E8h
UPX1:0040521B add eax, esi
UPX1:0040521D mov [edi], eax
UPX1:0040521F add edi, 5
UPX1:00405222 mov eax, ebx
UPX1:00405224 loop loc_4051FF
UPX1:00405226 lea edi, [esi+3000h]
UPX1:0040522C
UPX1:0040522C loc_40522C: ; CODE XREF: start+12Ej
UPX1:0040522C mov eax, [edi]
UPX1:0040522E or eax, eax
UPX1:00405230 jz short loc_40526E
UPX1:00405232 mov ebx, [edi+4]
UPX1:00405235 lea eax, [eax+esi+5000h]
UPX1:0040523C add ebx, esi
UPX1:0040523E push eax
UPX1:0040523F add edi, 8
UPX1:00405242 call dword ptr [esi+503Ch]
UPX1:00405248 xchg eax, ebp
UPX1:00405249
UPX1:00405249 loc_405249: ; CODE XREF: start+146j
UPX1:00405249 mov al, [edi]
UPX1:0040524B inc edi
UPX1:0040524C or al, al
UPX1:0040524E jz short loc_40522C
UPX1:00405250 mov ecx, edi
UPX1:00405252 push edi
UPX1:00405253 dec eax
UPX1:00405254 repne scasb
UPX1:00405256 push ebp
UPX1:00405257 call dword ptr [esi+5040h]
UPX1:0040525D or eax, eax
UPX1:0040525F jz short loc_405268
UPX1:00405261 mov [ebx], eax
UPX1:00405263 add ebx, 4
UPX1:00405266 jmp short loc_405249
UPX1:00405268 ; ---------------------------------------------------------------------------
UPX1:00405268
UPX1:00405268 loc_405268: ; CODE XREF: start+13Fj
UPX1:00405268 call dword ptr [esi+5044h]
UPX1:0040526E
UPX1:0040526E loc_40526E: ; CODE XREF: start+110j
UPX1:0040526E popa
UPX1:0040526F jmp near ptr dword_401000
程序完全变了,上面的代码也就是壳的代码、书上的脱壳思路是,用调试API一步一步的等待壳代码执行完,程序被复原的时候再修改那时候我们记录的jmp地址
在这段代码的最后面我们可以看到
jmp near ptr dword_401000
跳回的地址是00401000也就是我们没加壳的时候,程序开始的地址,我们就可以用调试API等到程序执行这一步,然后再修改之前那个
00401004
的值,那样我们就可以成功的脱壳了。
思路是这样的。
脱壳代码如下,我先是用win32asm写的
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
BREAK_POINT1 equ 00405120h
BREAK_POINT2 equ 00401000h
PATCH_POSITION equ 00401004h
.data?
align dword
stCT CONTEXT <?>
stDE DEBUG_EVENT <?>
stStartUp STARTUPINFO <>
stProcInfo PROCESS_INFORMATION <>
szBuffer db 1024 dup (?)
.const
dbPatched db 90h,90h
dbInt3 db 0cch
dbOldByte db 60h
szExecFilename db 'Test.exe',0
szErrExec db '无法装载执行文件!',0
.code
Start:
invoke GetStartupInfo,addr stStartUp
invoke CreateProcess,offset szExecFilename,NULL,NULL,NULL,NULL,DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS,NULL,\
NULL,offset stStartUp,offset stProcInfo
.if !eax
invoke MessageBox,NULL,addr szErrExec,NULL,MB_OK or MB_ICONSTOP
invoke ExitProcess,NULL
.endif
.while TRUE
invoke WaitForDebugEvent,addr stDE,INFINITE
.break .if stDE.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT
.if stDE.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT
invoke WriteProcessMemory,stProcInfo.hProcess,\
BREAK_POINT1,addr dbInt3,1,NULL
.elseif stDE.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
.if stDE.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT
mov stCT.ContextFlags,CONTEXT_FULL
invoke GetThreadContext,stProcInfo.hThread,addr stCT
.if stCT.regEip == BREAK_POINT1 + 1
dec stCT.regEip
invoke WriteProcessMemory,stProcInfo.hProcess,BREAK_POINT1,\
addr dbOldByte,1,NULL
or stCT.regFlag,100h
invoke SetThreadContext,stProcInfo.hThread,addr stCT
.endif
.elseif stDE.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP
mov stCT.ContextFlags,CONTEXT_FULL
invoke GetThreadContext,stProcInfo.hThread,addr stCT
.if stCT.regEip == BREAK_POINT2
invoke WriteProcessMemory,stProcInfo.hProcess,PATCH_POSITION,\
addr dbPatched,sizeof dbPatched,NULL
.else
or stCT.regFlag,100h
invoke SetThreadContext,stProcInfo.hThread,addr stCT
.endif
.endif
.endif
invoke ContinueDebugEvent,stDE.dwProcessId,stDE.dwThreadId,DBG_CONTINUE
.endw
invoke CloseHandle,stProcInfo.hProcess
invoke CloseHandle,stProcInfo.hThread
invoke ExitProcess,NULL
end Start
但是在win10下,却不行,,显示错误,但是我把这两个文件拷贝到win7虚拟机上却又是可以的
但是我用书上的那个加壳文件在win10上试了下。却又是可以的。我就实在不懂为什么了?小白的世界观已经崩塌了
于是我决定用c语言写出来。然后在vs上调试。看看到底是怎么回事
c语言代码如下
#include <Windows.h>
STARTUPINFO stStartUp;
PROCESS_INFORMATION stProcInfo;
DEBUG_EVENT stDE;
CONTEXT stCT;
char OldByte[] = "\x60";
char Patched[] = "\x90\x90";
char int3[] = "\xcc";
const DWORD BREAK_POINT1 = 0x00405120;
const DWORD BREAK_POINT2 = 0x00401000;
const DWORD PATCH_POSITION = 0x00401004;
int main()
{
GetStartupInfo(&stStartUp);
BOOL test = CreateProcess(TEXT("D:\\play\\Project4\\Debug\\Patch1Test1.exe"), NULL, NULL, NULL, NULL, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL,
NULL, &stStartUp, &stProcInfo);
int error = GetLastError();
if (!test){
MessageBox(NULL, TEXT("无法装载执行文件!"), NULL, MB_OK | MB_ICONSTOP);
return 0;
}
while (1)
{
WaitForDebugEvent(&stDE, INFINITE);
if (stDE.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
break;
else if (stDE.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
WriteProcessMemory(stProcInfo.hProcess, (LPVOID)0x00405120, int3, 1, NULL);
else if (stDE.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
if (stDE.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
stCT.ContextFlags = CONTEXT_FULL;
GetThreadContext(stProcInfo.hThread, &stCT);
if (stCT.Eip == BREAK_POINT1 + 1)
{
stCT.Eip--;
WriteProcessMemory(stProcInfo.hProcess, (LPVOID)0x00405120, OldByte, 1, NULL);
stCT.EFlags |= 0x100;
SetThreadContext(stProcInfo.hThread, &stCT);
}
}
else if (stDE.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
{
stCT.ContextFlags = CONTEXT_FULL;
GetThreadContext(stProcInfo.hThread, &stCT);
if (stCT.Eip == BREAK_POINT2)
WriteProcessMemory(stProcInfo.hProcess, (LPVOID)0x00401004, Patched, sizeof(Patched), NULL);
else
{
stCT.EFlags |= 0x100;
SetThreadContext(stProcInfo.hThread, &stCT);
}
}
ContinueDebugEvent(stDE.dwProcessId, stDE.dwThreadId, DBG_CONTINUE);
}
CloseHandle(stProcInfo.hProcess);
CloseHandle(stProcInfo.hThread);
return 0;
}
在vs的调试的时候..却又发生了我不能理解的事情,我已经把项目配置的ASLR关了。
而且我开的是一个新的进程,,调试的也是那个进程,应该不会影响吧。
在调试的时候却发现eip的地址是4215073
可是我之前反编译的明明是40开头的啊,,求各位大佬指点
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课