CTF-All-In-One/doc/6.1.22_pwn_hitconctf2016_sleepy_holder.md
2018-05-02 22:27:00 +08:00

351 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 6.1.22 pwn HITCONCTF2016 Sleepy_Holder
- [题目复现](#题目复现)
- [题目解析](#题目解析)
- [漏洞利用](#漏洞利用)
- [参考资料](#参考资料)
[下载文件](../src/writeup/6.1.22_pwn_hitconctf2016_sleepy_holder)
## 题目复现
```
$ file SleepyHolder
SleepyHolder: 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]=46f0e70abd9460828444d7f0975a8b2f2ddbad46, stripped
$ checksec -f SleepyHolder
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH Yes 0 2 SleepyHolder
$ strings libc.so.6 | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu3) stable release version 2.23, by Roland McGrath et al.
Compiled by GNU CC version 5.3.1 20160413.
```
64 位程序,开启了 Canary 和 NX默认开启 ASLR。
在 Ubuntu-16.04 上玩一下:
```
$ ./SleepyHolder
Waking Sleepy Holder up ...
Hey! Do you have any secret?
I can help you to hold your secrets, and no one will be able to see it :)
1. Keep secret
2. Wipe secret
3. Renew secret
1
What secret do you want to keep?
1. Small secret
2. Big secret
3. Keep a huge secret and lock it forever
1
Tell me your secret:
AAAA
1. Keep secret
2. Wipe secret
3. Renew secret
1
What secret do you want to keep?
1. Small secret
2. Big secret
3. Keep a huge secret and lock it forever
3
Tell me your secret:
CCCC
1. Keep secret
2. Wipe secret
3. Renew secret
3
Which Secret do you want to renew?
1. Small secret
2. Big secret
1
Tell me your secret:
BBBB
1. Keep secret
2. Wipe secret
3. Renew secret
2
Which Secret do you want to wipe?
1. Small secret
2. Big secret
1
```
这一题看起来和上一题 Secret_Holder 差不多。同样是 small、big、huge 三种 secret不同的是这里的 huge secret 是不可修改和删除的。另外在程序开始时会 sleep 几秒钟,不知道对利用有没有帮助。
## 题目解析
下面我们逐个来逆向这些功能。
#### Keep secret
```
[0x00400850]> pdf @ sub.What_secret_do_you_want_to_keep_93d
/ (fcn) sub.What_secret_do_you_want_to_keep_93d 452
| sub.What_secret_do_you_want_to_keep_93d ();
| ; var int local_14h @ rbp-0x14
| ; var int local_10h @ rbp-0x10
| ; var int local_8h @ rbp-0x8
| ; CALL XREF from 0x00400e3c (main)
| 0x0040093d push rbp
| 0x0040093e mov rbp, rsp
| 0x00400941 sub rsp, 0x20
| 0x00400945 mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40
| 0x0040094e mov qword [local_8h], rax
| 0x00400952 xor eax, eax
| 0x00400954 mov edi, str.What_secret_do_you_want_to_keep ; 0x400ee8 ; "What secret do you want to keep?"
| 0x00400959 call sym.imp.puts ; int puts(const char *s)
| 0x0040095e mov edi, str.1._Small_secret ; 0x400f09 ; "1. Small secret"
| 0x00400963 call sym.imp.puts ; int puts(const char *s)
| 0x00400968 mov edi, str.2._Big_secret ; 0x400f19 ; "2. Big secret"
| 0x0040096d call sym.imp.puts ; int puts(const char *s)
| 0x00400972 mov eax, dword [0x006020dc] ; [0x6020dc:4]=0
| 0x00400978 test eax, eax
| ,=< 0x0040097a jne 0x400986
| | 0x0040097c mov edi, str.3._Keep_a_huge_secret_and_lock_it_forever ; 0x400f28 ; "3. Keep a huge secret and lock it forever"
| | 0x00400981 call sym.imp.puts ; int puts(const char *s)
| | ; JMP XREF from 0x0040097a (sub.What_secret_do_you_want_to_keep_93d)
| `-> 0x00400986 lea rax, [local_10h]
| 0x0040098a mov edx, 4
| 0x0040098f mov esi, 0
| 0x00400994 mov rdi, rax
| 0x00400997 call sym.imp.memset ; void *memset(void *s, int c, size_t n)
| 0x0040099c lea rax, [local_10h]
| 0x004009a0 mov edx, 4
| 0x004009a5 mov rsi, rax
| 0x004009a8 mov edi, 0
| 0x004009ad mov eax, 0
| 0x004009b2 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| 0x004009b7 lea rax, [local_10h]
| 0x004009bb mov rdi, rax
| 0x004009be call sym.imp.atoi ; int atoi(const char *str)
| 0x004009c3 mov dword [local_14h], eax
| 0x004009c6 mov eax, dword [local_14h]
| 0x004009c9 cmp eax, 2 ; 2
| ,=< 0x004009cc je 0x400a3d
| | 0x004009ce cmp eax, 3 ; 3
| ,==< 0x004009d1 je 0x400a96
| || 0x004009d7 cmp eax, 1 ; 1
| ,===< 0x004009da je 0x4009e1
| ,====< 0x004009dc jmp 0x400aeb
| |||| ; JMP XREF from 0x004009da (sub.What_secret_do_you_want_to_keep_93d)
| |`---> 0x004009e1 mov eax, dword [0x006020e0] ; [0x6020e0:4]=0
| | || 0x004009e7 test eax, eax
| |,===< 0x004009e9 je 0x4009f0
| ,=====< 0x004009eb jmp 0x400aeb
| ||||| ; JMP XREF from 0x004009e9 (sub.What_secret_do_you_want_to_keep_93d)
| ||`---> 0x004009f0 mov esi, 0x28 ; '(' ; 40
| || || 0x004009f5 mov edi, 1
| || || 0x004009fa call sym.imp.calloc ; void *calloc(size_t nmeb, size_t size)
| || || 0x004009ff mov qword [0x006020d0], rax ; [0x6020d0:8]=0
| || || 0x00400a06 mov dword [0x006020e0], 1 ; [0x6020e0:4]=0
| || || 0x00400a10 mov edi, str.Tell_me_your_secret: ; 0x400f52 ; "Tell me your secret: "
| || || 0x00400a15 call sym.imp.puts ; int puts(const char *s)
| || || 0x00400a1a mov rax, qword [0x006020d0] ; [0x6020d0:8]=0
| || || 0x00400a21 mov edx, 0x28 ; '(' ; 40
| || || 0x00400a26 mov rsi, rax
| || || 0x00400a29 mov edi, 0
| || || 0x00400a2e mov eax, 0
| || || 0x00400a33 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| ||,===< 0x00400a38 jmp 0x400aeb
| ||||| ; JMP XREF from 0x004009cc (sub.What_secret_do_you_want_to_keep_93d)
| ||||`-> 0x00400a3d mov eax, dword [0x006020d8] ; [0x6020d8:4]=0
| |||| 0x00400a43 test eax, eax
| ||||,=< 0x00400a45 je 0x400a4c
| ,======< 0x00400a47 jmp 0x400aeb
| |||||| ; JMP XREF from 0x00400a45 (sub.What_secret_do_you_want_to_keep_93d)
| |||||`-> 0x00400a4c mov esi, 0xfa0 ; 4000
| ||||| 0x00400a51 mov edi, 1
| ||||| 0x00400a56 call sym.imp.calloc ; void *calloc(size_t nmeb, size_t size)
| ||||| 0x00400a5b mov qword [0x006020c0], rax ; [0x6020c0:8]=0
| ||||| 0x00400a62 mov dword [0x006020d8], 1 ; [0x6020d8:4]=0
| ||||| 0x00400a6c mov edi, str.Tell_me_your_secret: ; 0x400f52 ; "Tell me your secret: "
| ||||| 0x00400a71 call sym.imp.puts ; int puts(const char *s)
| ||||| 0x00400a76 mov rax, qword [0x006020c0] ; [0x6020c0:8]=0
| ||||| 0x00400a7d mov edx, 0xfa0 ; 4000
| ||||| 0x00400a82 mov rsi, rax
| ||||| 0x00400a85 mov edi, 0
| ||||| 0x00400a8a mov eax, 0
| ||||| 0x00400a8f call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| |||||,=< 0x00400a94 jmp 0x400aeb
| |||||| ; JMP XREF from 0x004009d1 (sub.What_secret_do_you_want_to_keep_93d)
| ||||`--> 0x00400a96 mov eax, dword [0x006020dc] ; [0x6020dc:4]=0
| |||| | 0x00400a9c test eax, eax
| ||||,==< 0x00400a9e je 0x400aa2
| ,=======< 0x00400aa0 jmp 0x400aeb
| ||||||| ; JMP XREF from 0x00400a9e (sub.What_secret_do_you_want_to_keep_93d)
| |||||`--> 0x00400aa2 mov esi, 0x61a80
| ||||| | 0x00400aa7 mov edi, 1
| ||||| | 0x00400aac call sym.imp.calloc ; void *calloc(size_t nmeb, size_t size)
| ||||| | 0x00400ab1 mov qword [0x006020c8], rax ; [0x6020c8:8]=0
| ||||| | 0x00400ab8 mov dword [0x006020dc], 1 ; [0x6020dc:4]=0
| ||||| | 0x00400ac2 mov edi, str.Tell_me_your_secret: ; 0x400f52 ; "Tell me your secret: "
| ||||| | 0x00400ac7 call sym.imp.puts ; int puts(const char *s)
| ||||| | 0x00400acc mov rax, qword [0x006020c8] ; [0x6020c8:8]=0
| ||||| | 0x00400ad3 mov edx, 0x61a80
| ||||| | 0x00400ad8 mov rsi, rax
| ||||| | 0x00400adb mov edi, 0
| ||||| | 0x00400ae0 mov eax, 0
| ||||| | 0x00400ae5 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| ||||| | 0x00400aea nop
| ||||| | ; XREFS: JMP 0x004009dc JMP 0x004009eb JMP 0x00400a38 JMP 0x00400a47 JMP 0x00400a94 JMP 0x00400aa0
| `````-`-> 0x00400aeb mov rax, qword [local_8h]
| 0x00400aef xor rax, qword fs:[0x28]
| ,=< 0x00400af8 je 0x400aff
| | 0x00400afa call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
| | ; JMP XREF from 0x00400af8 (sub.What_secret_do_you_want_to_keep_93d)
| `-> 0x00400aff leave
\ 0x00400b00 ret
```
#### Wipe secret
```
[0x00400850]> pdf @ sub.Which_Secret_do_you_want_to_wipe_b01
/ (fcn) sub.Which_Secret_do_you_want_to_wipe_b01 207
| sub.Which_Secret_do_you_want_to_wipe_b01 ();
| ; var int local_14h @ rbp-0x14
| ; var int local_10h @ rbp-0x10
| ; var int local_8h @ rbp-0x8
| ; CALL XREF from 0x00400e48 (main)
| 0x00400b01 push rbp
| 0x00400b02 mov rbp, rsp
| 0x00400b05 sub rsp, 0x20
| 0x00400b09 mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40
| 0x00400b12 mov qword [local_8h], rax
| 0x00400b16 xor eax, eax
| 0x00400b18 mov edi, str.Which_Secret_do_you_want_to_wipe ; 0x400f68 ; "Which Secret do you want to wipe?"
| 0x00400b1d call sym.imp.puts ; int puts(const char *s)
| 0x00400b22 mov edi, str.1._Small_secret ; 0x400f09 ; "1. Small secret"
| 0x00400b27 call sym.imp.puts ; int puts(const char *s)
| 0x00400b2c mov edi, str.2._Big_secret ; 0x400f19 ; "2. Big secret"
| 0x00400b31 call sym.imp.puts ; int puts(const char *s)
| 0x00400b36 lea rax, [local_10h]
| 0x00400b3a mov edx, 4
| 0x00400b3f mov esi, 0
| 0x00400b44 mov rdi, rax
| 0x00400b47 call sym.imp.memset ; void *memset(void *s, int c, size_t n)
| 0x00400b4c lea rax, [local_10h]
| 0x00400b50 mov edx, 4
| 0x00400b55 mov rsi, rax
| 0x00400b58 mov edi, 0
| 0x00400b5d mov eax, 0
| 0x00400b62 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| 0x00400b67 lea rax, [local_10h]
| 0x00400b6b mov rdi, rax
| 0x00400b6e call sym.imp.atoi ; int atoi(const char *str)
| 0x00400b73 mov dword [local_14h], eax
| 0x00400b76 mov eax, dword [local_14h]
| 0x00400b79 cmp eax, 1 ; 1
| ,=< 0x00400b7c je 0x400b85
| | 0x00400b7e cmp eax, 2 ; 2
| ,==< 0x00400b81 je 0x400ba0
| ,===< 0x00400b83 jmp 0x400bba
| ||| ; JMP XREF from 0x00400b7c (sub.Which_Secret_do_you_want_to_wipe_b01)
| ||`-> 0x00400b85 mov rax, qword [0x006020d0] ; [0x6020d0:8]=0
| || 0x00400b8c mov rdi, rax
| || 0x00400b8f call sym.imp.free ; void free(void *ptr)
| || 0x00400b94 mov dword [0x006020e0], 0 ; [0x6020e0:4]=0
| ||,=< 0x00400b9e jmp 0x400bba
| ||| ; JMP XREF from 0x00400b81 (sub.Which_Secret_do_you_want_to_wipe_b01)
| |`--> 0x00400ba0 mov rax, qword [0x006020c0] ; [0x6020c0:8]=0
| | | 0x00400ba7 mov rdi, rax
| | | 0x00400baa call sym.imp.free ; void free(void *ptr)
| | | 0x00400baf mov dword [0x006020d8], 0 ; [0x6020d8:4]=0
| | | 0x00400bb9 nop
| | | ; JMP XREF from 0x00400b83 (sub.Which_Secret_do_you_want_to_wipe_b01)
| | | ; JMP XREF from 0x00400b9e (sub.Which_Secret_do_you_want_to_wipe_b01)
| `-`-> 0x00400bba mov rax, qword [local_8h]
| 0x00400bbe xor rax, qword fs:[0x28]
| ,=< 0x00400bc7 je 0x400bce
| | 0x00400bc9 call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
| | ; JMP XREF from 0x00400bc7 (sub.Which_Secret_do_you_want_to_wipe_b01)
| `-> 0x00400bce leave
\ 0x00400bcf ret
```
#### Renew secret
```
[0x00400850]> pdf @ sub.Which_Secret_do_you_want_to_renew_bd0
/ (fcn) sub.Which_Secret_do_you_want_to_renew_bd0 259
| sub.Which_Secret_do_you_want_to_renew_bd0 ();
| ; var int local_14h @ rbp-0x14
| ; var int local_10h @ rbp-0x10
| ; var int local_8h @ rbp-0x8
| ; CALL XREF from 0x00400e54 (main)
| 0x00400bd0 push rbp
| 0x00400bd1 mov rbp, rsp
| 0x00400bd4 sub rsp, 0x20
| 0x00400bd8 mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40
| 0x00400be1 mov qword [local_8h], rax
| 0x00400be5 xor eax, eax
| 0x00400be7 mov edi, str.Which_Secret_do_you_want_to_renew ; 0x400f90 ; "Which Secret do you want to renew?"
| 0x00400bec call sym.imp.puts ; int puts(const char *s)
| 0x00400bf1 mov edi, str.1._Small_secret ; 0x400f09 ; "1. Small secret"
| 0x00400bf6 call sym.imp.puts ; int puts(const char *s)
| 0x00400bfb mov edi, str.2._Big_secret ; 0x400f19 ; "2. Big secret"
| 0x00400c00 call sym.imp.puts ; int puts(const char *s)
| 0x00400c05 lea rax, [local_10h]
| 0x00400c09 mov edx, 4
| 0x00400c0e mov esi, 0
| 0x00400c13 mov rdi, rax
| 0x00400c16 call sym.imp.memset ; void *memset(void *s, int c, size_t n)
| 0x00400c1b lea rax, [local_10h]
| 0x00400c1f mov edx, 4
| 0x00400c24 mov rsi, rax
| 0x00400c27 mov edi, 0
| 0x00400c2c mov eax, 0
| 0x00400c31 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| 0x00400c36 lea rax, [local_10h]
| 0x00400c3a mov rdi, rax
| 0x00400c3d call sym.imp.atoi ; int atoi(const char *str)
| 0x00400c42 mov dword [local_14h], eax
| 0x00400c45 mov eax, dword [local_14h]
| 0x00400c48 cmp eax, 1 ; 1
| ,=< 0x00400c4b je 0x400c54
| | 0x00400c4d cmp eax, 2 ; 2
| ,==< 0x00400c50 je 0x400c8a
| ,===< 0x00400c52 jmp 0x400cbd
| ||| ; JMP XREF from 0x00400c4b (sub.Which_Secret_do_you_want_to_renew_bd0)
| ||`-> 0x00400c54 mov eax, dword [0x006020e0] ; [0x6020e0:4]=0
| || 0x00400c5a test eax, eax
| ||,=< 0x00400c5c je 0x400c88
| ||| 0x00400c5e mov edi, str.Tell_me_your_secret: ; 0x400f52 ; "Tell me your secret: "
| ||| 0x00400c63 call sym.imp.puts ; int puts(const char *s)
| ||| 0x00400c68 mov rax, qword [0x006020d0] ; [0x6020d0:8]=0
| ||| 0x00400c6f mov edx, 0x28 ; '(' ; 40
| ||| 0x00400c74 mov rsi, rax
| ||| 0x00400c77 mov edi, 0
| ||| 0x00400c7c mov eax, 0
| ||| 0x00400c81 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| ,====< 0x00400c86 jmp 0x400cbd
| |||| ; JMP XREF from 0x00400c5c (sub.Which_Secret_do_you_want_to_renew_bd0)
| ,===`-> 0x00400c88 jmp 0x400cbd
| |||| ; JMP XREF from 0x00400c50 (sub.Which_Secret_do_you_want_to_renew_bd0)
| |||`--> 0x00400c8a mov eax, dword [0x006020d8] ; [0x6020d8:4]=0
| ||| 0x00400c90 test eax, eax
| ||| ,=< 0x00400c92 je 0x400cbc
| ||| | 0x00400c94 mov edi, str.Tell_me_your_secret: ; 0x400f52 ; "Tell me your secret: "
| ||| | 0x00400c99 call sym.imp.puts ; int puts(const char *s)
| ||| | 0x00400c9e mov rax, qword [0x006020c0] ; [0x6020c0:8]=0
| ||| | 0x00400ca5 mov edx, 0xfa0 ; 4000
| ||| | 0x00400caa mov rsi, rax
| ||| | 0x00400cad mov edi, 0
| ||| | 0x00400cb2 mov eax, 0
| ||| | 0x00400cb7 call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| ||| | ; JMP XREF from 0x00400c92 (sub.Which_Secret_do_you_want_to_renew_bd0)
| ||| `-> 0x00400cbc nop
| ||| ; JMP XREF from 0x00400c52 (sub.Which_Secret_do_you_want_to_renew_bd0)
| ||| ; JMP XREF from 0x00400c86 (sub.Which_Secret_do_you_want_to_renew_bd0)
| ||| ; JMP XREF from 0x00400c88 (sub.Which_Secret_do_you_want_to_renew_bd0)
| ```---> 0x00400cbd mov rax, qword [local_8h]
| 0x00400cc1 xor rax, qword fs:[0x28]
| ,=< 0x00400cca je 0x400cd1
| | 0x00400ccc call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
| | ; JMP XREF from 0x00400cca (sub.Which_Secret_do_you_want_to_renew_bd0)
| `-> 0x00400cd1 leave
\ 0x00400cd2 ret
```
## 漏洞利用
## 参考资料
- https://ctftime.org/task/4812
- https://github.com/mehQQ/public_writeup/tree/master/hitcon2016/SleepyHolder