u // 反汇编,为了确保能够正确反汇编,使用cl /Fd /Zi xx.c编译文件,以生成符号表文件xx.pdb u xx L11 // 相当于反汇编xx函数0x11条指令 Alt+7 // 打开程序上下文窗口(disassembly) bp // 打断点,例如在foo函数第0x19条(16进制)汇编指令上打断点,就有bp overflow!foo + 19 g or F5 // 启动进程 dd xx // 输出xx的128个字节 da xx // 以Ascii码输出xx指向的字符串 p // 单步执行(F10) .imgscan // 查看内存中的进程映像 s 7c800000 L12b000 ff d4 // 起始地址为7c800000,size为12b000,找16进制为ff d4对应的位置 s -u 522e0000 527d1000 "web" //表示在522e0000 和527d1000之间搜索Unicode字符串"web" ? // 显示常规命令,例如 ?0x000003cf,输出975
#ifdef __cplusplus // If used by C++ code extern"C" { // we need to export the C interface #endif __declspec(dllexport) int __cdecl myPuts(char *lpszMsg) { puts((char *)lpszMsg); return1; } __declspec(dllexport) int __cdecl myPutws(LPWSTR lpszMsg) { _putws(lpszMsg); return1; } __declspec(dllexport) int __cdecl myAdd(int a, int b) { return a + b; } __declspec(dllexport) float __cdecl myMul(float a, float b) { return a * b; } #ifdef __cplusplus } #endif
unsignedlongGetKernel32Addr() { unsignedlong pAddress; __asm{ mov eax, fs:30h ; PEB base mov eax, [eax+0ch] ; PEB_LER_DATA mov ebx, [eax+1ch] ; The first element // kernel32.dll,如果去掉 mov ebx,[ebx]就是 ntdll.dll // 此时ebx为LIST_ENTRY,便可以理解了 mov ebx,[ebx] ; Next element mov eax,[ebx+8] ; Base address of second module mov pAddress,eax ; Save it to local variable }; printf("Base address of kernel32.dll is %p\n", pAddress); return pAddress; } voidmain(void) { GetKernel32Addr(); }
__asm{ mov edx, fs:30h ; PEB base mov edx, [edx+0ch] ; PEB_LER_DATA mov edx, [edx+1ch] ; The first element of InInitOrderModuleList // base of kernel32.dll mov edx, [edx] ; Next element mov eax, [edx+8] ; Base address of second module mov pBaseOfModule,eax ; Save it to local variable mov ebx, eax ; Base address of kernel32.dll, save it to ebx // get the addrs of first function ========= // 注意:获得的e_lfanew, DataDirectory[0]是相对地址 mov edx,[ebx+3ch] ; e_lfanew mov edx,[edx+ebx+78h] ; DataDirectory[0] add edx,ebx ; RVA + base mov esi,edx ; Save first DataDirectory to esi // get fields of IMAGE_EXPORT_DIRECTORY pNameOfModule mov edx,[esi+0ch] ; Module Name add edx,ebx ; RVA + base mov pNameOfModule,edx ; Save it to local variable mov edx,[esi+1ch] ; AddressOfFunctions RVA add edx,ebx ; RVA + base mov pAddressOfFunctions,edx ; Save it to local variable mov edx,[esi+20h] ; AddressOfNames RVA add edx,ebx ; RVA + base mov pAddress0fNames,edx ; Save it to local variable } printf("Name of Module:%s\n\tBase of Moudle=%p\n", (char *)pNameOfModule,pBaseOfModule); printf("First Function:\n\tAddress=0x%p\n\tName=%s\n", (pBaseOfModule + *((unsignedlong *) (pAddressOfFunctions))), (char *)(pBaseOfModule + *((unsignedlong *) (pAddress0fNames)))) ; }
//hash_proc: you should put the address of the string to edi //when ret, the hash value stores in eax hash_proc: // save ebx,ecx,edx,edi push ebx ; push ecx ; push edx ; push edi ; xor edx,edx ; edx = h hash_loop: ; movsx eax,byte ptr [edi] ; [eax]=*c ==> eax cmp eax,0 ; je exit_hash_proc ; mov ebx,edx ; h ==> ebx mov ecx,edx ; h ==> ecx shl ebx,19h ; h << 25 shr ecx,7 ; h >> 7 or ebx,ecx ; ((h << 25) | (h >> 7)) mov edx,ebx ; add edx,eax ; inc edi; ; jmp hash_loop ; exit_hash_proc: ; mov eax,edx ; save hash to eax // restore ebx,ecx,edx,edi pop edi ; pop edx ; pop ecx ; pop ebx ; retn ;
unsignedlongGetHash(char * c) { unsignedlong h=0; while(*c) { h = ( ( h << 25 ) | ( h >> 7 ) ) + *(c++); } return h; }
unsignedlongfindFuncAddr(unsignedlong lHash) // lHash: hash of the function name. { unsignedlong lHashFunAddr;
__asm{ // load lHash to edx push lHash; pop edx; // call some functions to do the job. call get_base_address; // the base address is 0, done. cmp eax,0; jle end_of_findFuncAddr; if ecx <=0 done. // save the base to ebx; mov ebx,eax; call get_function_addr; // finish all job. jmp end_of_findFuncAddr; // Define some sub processes here. =========================================== // begin of get_base_address ================================== // get_base_address: put the DLL nIndex to ecx. eax=return value get_base_address: mov eax, fs:30h ; PEB base mov eax, [eax+0ch] ; PEB_LER_DATA // base of first element mov eax,[eax+1ch] ; The first element of InInitOrderModuleList mov eax,[eax] ; Next element mov eax,[eax+8] ; eax = Base address of the module retn; // end of get_base_address ======================================
// begin of get_function_addr ================================= // get_function_addr, in: ebx=base, edx=hash(name); out:eax=return value get_function_addr: // get the addrs of first function ========= mov eax,[ebx+3ch] ; e_lfanew mov eax,[eax+ebx+78h] ; DataDirectory[0] add eax,ebx ; RVA + base mov esi,eax ; Save first DataDirectory to esi // get fields of IMAGE_EXPORT_DIRECTORY pNameOfModule //mov eax,[esi+0ch] ; Name RVA, real address should "add eax,ebx" //mov eax,[esi+14h] ; NumberOfFunctions //mov eax,[esi+18h] ; NumberOfNames //mov eax,[esi+1ch] ; AddressOfFunctions RVA //mov eax,[esi+20h] ; AddressOfNames RVA //mov eax,[esi+24h] ; AddressOfNameOrdinals RVA mov ecx,[esi+18h] ; NumberOfNames compare_names_hash: mov eax, [esi+20h] ; AddressOfNames RVA add eax, ebx ; rva2va mov eax, [eax+ecx*4-4] ; NamesAddress RVA add eax, ebx ; rva2va, now eax store the address of the name
push edi ; save edi to stack mov edi,eax ; put the address of the string to edi call hash_proc; ; gethash pop edi ; restor edi from stack
cmp eax,edx; ; compare to hash; je done_find_hash; //cmp ebx, [edi] ; compare to hash //jnz short find_start loop compare_names_hash; xor eax,eax; jmp done_get_function_addr; done_find_hash: mov eax, [esi+1ch] ; AddressOfFunctions RVA add eax, ebx ; rva2va mov eax, [eax+ecx*4-4] ; FunctionAddress RVA add eax, ebx ; rva2va, now eax store the address of the Function done_get_function_addr: retn; // end of get_function_addr ======================================
// begin of hash_process ====================================== // hash_proc: you should put the address of the string to edi // when ret, the hash value stores in eax hash_proc: // save ebx,ecx,edx,edi push ebx ; push ecx ; push edx ; push edi ; xor edx,edx ; edx = h hash_loop: ; movsx eax,byte ptr [edi] ; [eax]=*c ==> eax cmp eax,0 ; je exit_hash_proc ; mov ebx,edx ; h ==> ebx mov ecx,edx ; h ==> ecx shl ebx,19h ; h << 25 shr ecx,7 ; ( h >> 7 ) or ebx,ecx ; ( ( h << 25 ) | ( h >> 7 ) ) mov edx,ebx ; add edx,eax ; inc edi; ; jmp hash_loop ; exit_hash_proc: ; mov eax,edx ; save hash to eax // restore ebx,ecx,edx,edi pop edi ; pop edx ; pop ecx ; pop ebx ; retn ; // end of hash_process ======================================== end_of_findFuncAddr: mov lHashFunAddr,eax; }; return lHashFunAddr; } voidmain(void) { printf("LoadLibraryA\t=%p\tfindHashaddr: %p\n", LoadLibraryA, findFuncAddr(GetHash("LoadLibraryA"))); printf("CreateProcessA\t=%p\tfindHashaddr: %p\n", CreateProcessA,findFuncAddr(GetHash("CreateProcessA"))); }
pop edx; ; //edx=GetHash("CreateProcessA"); call findHashFuncAddrProc; // eax=address of function mov esi,eax; ;// esi=CreateProcessA pop edx; ;// edx=GetHash("ExitProcess"); call findHashFuncAddrProc; // eax=address of function mov ebx,eax; ;// ebx=CloseHandle
call doCommandProc; // eax
jmp end_of_this_function; // finish all job. doCommandProc: push ecx; push edx; push esi; push edi; push ebp; mov ebp,esp;
mov edx,edi; //edx=szCmdLine sub esp, 54h; mov edi, esp; push 14h; pop ecx; xor eax,eax; stack_zero: mov [edi+ecx*4], eax; loop stack_zero;
donot_closehandle: mov esp,ebp; pop ebp; pop edi; pop esi; pop edx; pop ecx; retn;
findHashFuncAddrProc: push esi; push ebx; push ecx; push edx; call get_base_address; cmp eax,0 ; // the base address is 0, done. jle end_of_findHashFuncAddrProc; if ecx <=0 done. mov ebx,eax ; // save the base to ebx; call get_function_addr; end_of_findHashFuncAddrProc: pop edx; pop ecx; pop ebx; pop esi; retn;
get_base_address: mov eax, fs:30h ; PEB base mov eax, [eax+0ch] ; PEB_LER_DATA mov eax,[eax+1ch] ; The first element of InInitOrderModuleList mov eax,[eax] ; Next element mov eax,[eax+8] ; eax = Base address of the module retn;
get_function_addr: mov eax,[ebx+3ch] ; e_lfanew mov eax,[eax+ebx+78h] ; DataDirectory[0] add eax,ebx ; RVA + base mov esi,eax ; Save first DataDirectory to esi mov ecx,[esi+18h] ; NumberOfNames compare_names_hash: mov eax, [esi+20h] ; AddressOfNames RVA add eax, ebx ; rva2va mov eax, [eax+ecx*4-4] ; NamesAddress RVA add eax, ebx ; rva2va, now eax store the address of the name
push edi ; save edi to stack mov edi,eax ; put the address of the string to edi call hash_proc; ; gethash pop edi ; restor edi from stack
cmp eax,edx; ; compare to hash; je done_find_hash; loop compare_names_hash; xor eax,eax; jmp done_get_function_addr; done_find_hash: mov eax, [esi+1ch] ; AddressOfFunctions RVA add eax, ebx ; rva2va mov eax, [eax+ecx*4-4] ; FunctionAddress RVA add eax, ebx ; rva2va, now eax store the address of the Function done_get_function_addr: retn;
hash_proc: // save ebx,ecx,edx,edi push ebx ; push ecx ; push edx ; push edi ; xor edx,edx ; edx = h hash_loop: ; movsx eax,byte ptr [edi] ; [eax]=*c ==> eax cmp eax,0 ; je exit_hash_proc ; mov ebx,edx ; h ==> ebx mov ecx,edx ; h ==> ecx shl ebx,19h ; h << 25 shr ecx,7 ; h >> 7 or ebx,ecx ; ((h << 25) | (h >> 7)) mov edx,ebx ; add edx,eax ; inc edi; ; jmp hash_loop ; exit_hash_proc: ; mov eax,edx ; save hash to eax // restore ebx,ecx,edx,edi pop edi ; pop edx ; pop ecx ; pop ebx ; retn ; end_of_this_function: PROC_END; // End of the code }; }