|
(0012F010 40 85 53 00 )
附录:附上部分DEBUG_EVENT结构的声明:(注释是我加的)
typedef struct _DEBUG_EVENT {
DWORD dwDebugEventCode; //偏移0x0
DWORD dwProcessId; //偏移0x4
DWORD dwThreadId; //偏移0x8
union {
EXCEPTION_DEBUG_INFO Exception; //偏移0xC
CREATE_THREAD_DEBUG_INFO CreateThread;
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
EXIT_THREAD_DEBUG_INFO ExitThread;
EXIT_PROCESS_DEBUG_INFO ExitProcess;
LOAD_DLL_DEBUG_INFO LoadDll;
UNLOAD_DLL_DEBUG_INFO UnloadDll;
OUTPUT_DEBUG_STRING_INFO DebugString;
RIP_INFO RipInfo;
} u;
} DEBUG_EVENT, *LPDEBUG_EVENT;
typedef struct _EXCEPTION_DEBUG_INFO { //即异常代码是0x00000001时的结构
EXCEPTION_RECORD ExceptionRecord; //偏移0xC;0x80000001为STATUS_GUARD_PAGE_VIOLATION(NT)
//0xC0000005为STATUS_ACCESS_VIOLATION(WIN (win 9x)
DWORD dwFirstChance;
} EXCEPTION_DEBUG_INFO, *LPEXCEPTION_DEBUG_INFO;
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode; //偏移0xc
DWORD ExceptionFlags; //偏移0x10
struct _EXCEPTION_RECORD *ExceptionRecord; //偏移0x14
PVOID ExceptionAddress; //偏移0x18
DWORD NumberParameters;
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
[方法三],bpx SetProcessWorkingSetSize(使用DriverSuite2.7中的softice4.2.7)
bpx SetProcessWorkingSetSize去找OEP 一旦softice中断了,检查softice是否在Get Right的领空,如果不在则按F5直到softice在Get Right 的领空中断。然后按F12辅之以F10跟踪过去一些指令,直到你看到一个"call edi"指令,停在那儿,然后写下edi的值。那就是OEP。
第三步,进入调试循环并打补丁
移除所有断点,然后"bpx WriteProcessMemory"。按F5,一旦softice中断按F12 两次你将会在通常所谓的Armadillo的解码routine, 这个你在先前的Armadillo版本中已经见过的。
005F88C7 6A 00 PUSH 0
;flag如果是0表明解码,如果是1则 encrypt
005F88C9 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
;mov ecx, [ebp+key_address]
005F88CC 51 PUSH ECX
005F88CD 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8]
;mov edx, [ebp+块数]
005F88D0 52 PUSH EDX
005F88D1 E8 76010000 CALL getright.005F8A4C
;<--这里CALL 005F8A4C对异常页解码,005F8A4C其实是用来加解码的,还有另外一个地方调用了它,用来重新加密或者破坏已使用的块来避免被dump。解码 CALL= 5F88D1 加密 CALL = 5F8A24
005F88D6 83C4 0C ADD ESP,0C
;==你应该返回到这里!!!!
005F88D9 25 FF000000 AND EAX,0FF
005F88DE 85C0 TEST EAX,EAX
005F88E0 75 07 JNZ SHORT getright.005F88E9
;解码成功?
005F88E2 32C0 XOR AL,AL
005F88E4 E9 5D010000 JMP getright.005F8A46
简要分析005F88D1处的解码函数“CALL getright.005F8A4C”。以下是它的流程:
1。调用VirtualProtectEx将异常页面属性改为PAGE_READWRITE
2。调用ReadProcessMemory,将异常页面读入
3。解码。
4。调用WriteProcessMemory,写入正确代码。
5。调用VirtualProtectEx将页面属性改为PAGE_EXECUTE_READ
试着在这些指令间循环以迫使它解码所有的代码段然后你将会得到一堆垃圾,因为现在每1000h bytes 的内存块都有一个不同的解码 key。所以我们将必须去找出解码 key的产生routine。再继续跟踪你将会看到:
005F88E9 A1 C83A6100 MOV EAX,DWORD PTR DS:[613AC8]
;<==注意!!! DS:[613AC8]存放有已解码的块数,[613AC8]是一个记数器,解码成功后加一,有什么用呢?看后面
005F88EE 83C0 01 ADD EAX,1
005F88F1 A3 C83A6100 MOV DWORD PTR DS:[613AC8],EAX
;已经解码的内存块数量加1
--------SNIP-----------
005F8938 8B15 C83A6100 /MOV EDX,DWORD PTR DS:[613AC8]
;把已经解码的块的数量给 EDX,用于当解码块时比较
005F893E 3B15 A4066100 |CMP EDX,DWORD PTR DS:[6106A4]
;DS:[6106A4]存放着允许解码块数的最大值
005F8944 0F8E FA000000 |JLE getright.005F8A44
;当小于时继续解码,如果大于,则不跳,前往5F8A24执行加密CALL
上一页 1 2 3 4 下一页 |