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

19 KiB
Raw Blame History

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

漏洞利用

参考资料