diff --git a/README.md b/README.md index 7f800dc..ad687fe 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ - [4.3 GCC 编译参数解析](doc/4.3_gcc_arg.md) - [4.4 GCC 堆栈保护技术](doc/4.4_gcc_sec.md) - [4.5 Z3 约束求解器](doc/4.5_z3.md) + - [4.6 one-gadget RCE](doc/4.6_one-gadget_rce.md) - [4.7 通用 gadget](doc/4.7_common_gadget.md) - [4.8 使用 DynELF 泄露函数地址](doc/4.8_dynelf.md) - [4.9 给 ELF 文件打 patch](doc/4.9_patch_elf.md) diff --git a/SUMMARY.md b/SUMMARY.md index e31f314..09a51d1 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -55,6 +55,7 @@ GitHub 地址:https://github.com/firmianay/CTF-All-In-One * [4.3 GCC 编译参数解析](doc/4.3_gcc_arg.md) * [4.4 GCC 堆栈保护技术](doc/4.4_gcc_sec.md) * [4.5 Z3 约束求解器](doc/4.5_z3.md) + * [4.6 one-gadget RCE](doc/4.6_one-gadget_rce.md) * [4.7 通用 gadget](doc/4.7_common_gadget.md) * [4.8 使用 DynELF 泄露函数地址](doc/4.8_dynelf.md) * [4.9 给 ELF 文件打 patch](doc/4.9_patch_elf.md) diff --git a/doc/3.3.4_rop.md b/doc/3.3.4_rop.md index c1e8df7..71cc090 100644 --- a/doc/3.3.4_rop.md +++ b/doc/3.3.4_rop.md @@ -1260,7 +1260,7 @@ payload_2 += p64(xchg_rax_rsp) ## 练习 -ROP Emporium 中有几个 64 位程序在这里没有给出 payload,就留作联系吧,答案都可以在这里找到:[ROP Emporium Writeup](https://firmianay.github.io/2017/11/02/rop_emporium.html) +ROP Emporium 中有几个 64 位程序在这里没有给出 payload,就留作练习吧,答案都可以在这里找到:[ROP Emporium Writeup](https://firmianay.github.io/2017/11/02/rop_emporium.html) ## 更多资料 diff --git a/doc/4.6_one-gadget_rce.md b/doc/4.6_one-gadget_rce.md new file mode 100644 index 0000000..47ce54f --- /dev/null +++ b/doc/4.6_one-gadget_rce.md @@ -0,0 +1 @@ +# 4.6 one-gadget RCE diff --git a/doc/4_tips.md b/doc/4_tips.md index 41f3564..bbcb3b4 100644 --- a/doc/4_tips.md +++ b/doc/4_tips.md @@ -5,6 +5,7 @@ - [4.3 GCC 编译参数解析](4.3_gcc_arg.md) - [4.4 GCC 堆栈保护技术](4.4_gcc_sec.md) - [4.5 Z3 约束求解器](4.5_z3.md) +- [4.6 one-gadget RCE](4.6_one-gadget_rce.md) - [4.7 通用 gadget](4.7_common_gadget.md) - [4.8 使用 DynELF 泄露函数地址](4.8_dynelf.md) - [4.9 给 ELF 文件打 patch](4.9_patch_elf.md) diff --git a/doc/6.1.8_pwn_dctf2017_flex.md b/doc/6.1.8_pwn_dctf2017_flex.md index 14ac121..26adfb5 100644 --- a/doc/6.1.8_pwn_dctf2017_flex.md +++ b/doc/6.1.8_pwn_dctf2017_flex.md @@ -1,14 +1,11 @@ # 6.1.8 pwn DCTF2017 Flex -- [C++ 异常机制](#c-异常机制) - [题目解析](#题目解析) - [参考资料](#参考资料) [下载文件](../src/writeup/6.1.8_pwn_dctf2017_flex) -## C++ 异常机制 - ## 题目解析 ``` $ file flex @@ -17,6 +14,240 @@ $ checksec -f flex 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 4 flex ``` +随便玩一下,了解程序的基本功能: +``` +$ ./flex +1.start flexmd5 +2.start flexsha256 +3.start flexsha1 +4.test security +0 quit +option: +1 +FlexMD5 bruteforce tool V0.1 +custom md5 state (yes/No) +No +custom charset (yes/No) +yes +charset length: +10 +charset: +a +bruteforce message pattern: +aaaa +``` +第四个选项很吸引人,但似乎没有发现什么突破点,而第一个选项可以输入的东西较多,问题应该在这里,查看该函数 `sub.bruteforcing_start:_85f`: +``` + 0x00401500 55 push rbp +| 0x00401501 4889e5 mov rbp, rsp +| 0x00401504 4883ec10 sub rsp, 0x10 +| 0x00401508 e83bfcffff call sub.FlexMD5_bruteforce_tool_V0.1_148 +| 0x0040150d e87dfaffff call fcn.00400f8f +| 0x00401512 bf4f464000 mov edi, str.bruteforcing_start: ; 0x40464f ; "bruteforcing start:" +| 0x00401517 e8b4f6ffff call sym.imp.puts ; int puts(const char *s) +| ; JMP XREF from 0x00401534 (sub.bruteforcing_start:_500) +| .-> 0x0040151c e88cfeffff call sub.strlen_3ad ; size_t strlen(const char *s) +| : 0x00401521 85c0 test eax, eax +| : 0x00401523 0f94c0 sete al +| : 0x00401526 84c0 test al, al +| ,==< 0x00401528 740c je 0x401536 +| |: 0x0040152a bf01000000 mov edi, 1 +| |: 0x0040152f e83cf7ffff call sym.imp.sleep ; int sleep(int s) +| |`=< 0x00401534 ebe6 jmp 0x40151c +| | ; JMP XREF from 0x00401528 (sub.bruteforcing_start:_500) +| | ; JMP XREF from 0x0040155d (sub.bruteforcing_start:_500 + 93) +| `.-> 0x00401536 b800000000 mov eax, 0 +| ,==< 0x0040153b eb22 jmp 0x40155f + |: 0x0040153d 4883fa01 cmp rdx, 1 ; 1 + ,===< 0x00401541 7408 je 0x40154b + ||: 0x00401543 4889c7 mov rdi, rax + ||: 0x00401546 e8f5f7ffff call sym.imp._Unwind_Resume + ||: ; JMP XREF from 0x00401541 (sub.bruteforcing_start:_500 + 65) + `---> 0x0040154b 4889c7 mov rdi, rax + |: 0x0040154e e8bdf7ffff call sym.imp.__cxa_begin_catch + |: 0x00401553 8b00 mov eax, dword [rax] + |: 0x00401555 8945fc mov dword [rbp - 4], eax + |: 0x00401558 e8a3f7ffff call sym.imp.__cxa_end_catch + |`=< 0x0040155d ebd7 jmp 0x401536 ; sub.bruteforcing_start:_500+0x36 +| | ; JMP XREF from 0x0040153b (sub.bruteforcing_start:_500) +| `--> 0x0040155f c9 leave +\ 0x00401560 c3 ret +``` +函数 `sub.FlexMD5_bruteforce_tool_V0.1_148`: +``` +[0x00400d80]> pdf @ sub.FlexMD5_bruteforce_tool_V0.1_148 +/ (fcn) sub.FlexMD5_bruteforce_tool_V0.1_148 613 +| sub.FlexMD5_bruteforce_tool_V0.1_148 (); +| ; var int local_124h @ rbp-0x124 +| ; var int local_120h @ rbp-0x120 +| ; var int local_18h @ rbp-0x18 +| ; CALL XREF from 0x00401508 (sub.bruteforcing_start:_500) +| 0x00401148 55 push rbp +| 0x00401149 4889e5 mov rbp, rsp +| 0x0040114c 53 push rbx +| 0x0040114d 4881ec280100. sub rsp, 0x128 +| 0x00401154 64488b042528. mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40 +| 0x0040115d 488945e8 mov qword [local_18h], rax +| 0x00401161 31c0 xor eax, eax +| 0x00401163 bf47454000 mov edi, str.FlexMD5_bruteforce_tool_V0.1 ; 0x404547 ; "FlexMD5 bruteforce tool V0.1" +| 0x00401168 e863faffff call sym.imp.puts ; int puts(const char *s) +| 0x0040116d bf64454000 mov edi, str.custom_md5_state__yes_No_ ; 0x404564 ; "custom md5 state (yes/No)" +| 0x00401172 e859faffff call sym.imp.puts ; int puts(const char *s) +| 0x00401177 488d85e0feff. lea rax, [local_120h] +| 0x0040117e be04000000 mov esi, 4 +| 0x00401183 4889c7 mov rdi, rax +| 0x00401186 e8ebfcffff call sub.read_e76 ; ssize_t read(int fildes, void *buf, size_t nbyte) +| 0x0040118b 488d85e0feff. lea rax, [local_120h] +| 0x00401192 ba03000000 mov edx, 3 +| 0x00401197 be7e454000 mov esi, 0x40457e ; "yes" +| 0x0040119c 4889c7 mov rdi, rax +| 0x0040119f e85cfaffff call sym.imp.strncmp ; int strncmp(const char *s1, const char *s2, size_t n) +| 0x004011a4 85c0 test eax, eax +| ,=< 0x004011a6 755e jne 0x401206 +| | 0x004011a8 c705f24f2000. mov dword [0x006061a4], 1 ; [0x6061a4:4]=0 +| | 0x004011b2 bf82454000 mov edi, str.initial_state_0_: ; 0x404582 ; "initial state[0]:" +| | 0x004011b7 e814faffff call sym.imp.puts ; int puts(const char *s) +| | 0x004011bc e884fdffff call sub.atoi_f45 ; int atoi(const char *str) +| | 0x004011c1 8905e94f2000 mov dword [0x006061b0], eax ; [0x6061b0:4]=0 +| | 0x004011c7 bf94454000 mov edi, str.initial_state_1_: ; 0x404594 ; "initial state[1]:" +| | 0x004011cc e8fff9ffff call sym.imp.puts ; int puts(const char *s) +| | 0x004011d1 e86ffdffff call sub.atoi_f45 ; int atoi(const char *str) +| | 0x004011d6 8905d84f2000 mov dword [0x006061b4], eax ; [0x6061b4:4]=0 +| | 0x004011dc bfa6454000 mov edi, str.initial_state_2_: ; 0x4045a6 ; "initial state[2]:" +| | 0x004011e1 e8eaf9ffff call sym.imp.puts ; int puts(const char *s) +| | 0x004011e6 e85afdffff call sub.atoi_f45 ; int atoi(const char *str) +| | 0x004011eb 8905c74f2000 mov dword [0x006061b8], eax ; [0x6061b8:4]=0 +| | 0x004011f1 bfb8454000 mov edi, str.initial_state_3_: ; 0x4045b8 ; "initial state[3]:" +| | 0x004011f6 e8d5f9ffff call sym.imp.puts ; int puts(const char *s) +| | 0x004011fb e845fdffff call sub.atoi_f45 ; int atoi(const char *str) +| | 0x00401200 8905b64f2000 mov dword [0x006061bc], eax ; [0x6061bc:4]=0 +| | ; JMP XREF from 0x004011a6 (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `-> 0x00401206 bfca454000 mov edi, str.custom_charset__yes_No_ ; 0x4045ca ; "custom charset (yes/No)" +| 0x0040120b e8c0f9ffff call sym.imp.puts ; int puts(const char *s) +| 0x00401210 488d85e0feff. lea rax, [local_120h] +| 0x00401217 be04000000 mov esi, 4 +| 0x0040121c 4889c7 mov rdi, rax +| 0x0040121f e852fcffff call sub.read_e76 ; ssize_t read(int fildes, void *buf, size_t nbyte) +| 0x00401224 488d85e0feff. lea rax, [local_120h] +| 0x0040122b ba03000000 mov edx, 3 +| 0x00401230 be7e454000 mov esi, 0x40457e ; "yes" +| 0x00401235 4889c7 mov rdi, rax +| 0x00401238 e8c3f9ffff call sym.imp.strncmp ; int strncmp(const char *s1, const char *s2, size_t n) +| 0x0040123d 85c0 test eax, eax +| ,=< 0x0040123f 0f858a000000 jne 0x4012cf +| | 0x00401245 c705554f2000. mov dword [0x006061a4], 1 ; [0x6061a4:4]=0 +| | 0x0040124f bfe2454000 mov edi, str.charset_length: ; 0x4045e2 ; "charset length:" +| | 0x00401254 e877f9ffff call sym.imp.puts ; int puts(const char *s) +| | 0x00401259 e8e7fcffff call sub.atoi_f45 ; int atoi(const char *str) +| | 0x0040125e 8905ac4e2000 mov dword [0x00606110], eax ; [0x606110:4]=62 +| | 0x00401264 8b05a64e2000 mov eax, dword [0x00606110] ; [0x606110:4]=62 +| | 0x0040126a 3d00010000 cmp eax, 0x100 ; 256 +| ,==< 0x0040126f 7e22 jle 0x401293 +| || 0x00401271 bf04000000 mov edi, 4 +| || 0x00401276 e855faffff call sym.imp.__cxa_allocate_exception +| || 0x0040127b c70002000000 mov dword [rax], 2 +| || 0x00401281 ba00000000 mov edx, 0 +| || 0x00401286 be70616000 mov esi, obj.typeinfoforint ; 0x606170 +| || 0x0040128b 4889c7 mov rdi, rax +| || 0x0040128e e85dfaffff call sym.imp.__cxa_throw +| || ; JMP XREF from 0x0040126f (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `--> 0x00401293 bff2454000 mov edi, str.charset: ; 0x4045f2 ; "charset:" +| | 0x00401298 e833f9ffff call sym.imp.puts ; int puts(const char *s) +| | 0x0040129d 8b056d4e2000 mov eax, dword [0x00606110] ; [0x606110:4]=62 +| | 0x004012a3 83c001 add eax, 1 +| | 0x004012a6 89c2 mov edx, eax +| | 0x004012a8 488d85e0feff. lea rax, [local_120h] +| | 0x004012af 89d6 mov esi, edx +| | 0x004012b1 4889c7 mov rdi, rax +| | 0x004012b4 e8bdfbffff call sub.read_e76 ; ssize_t read(int fildes, void *buf, size_t nbyte) +| | 0x004012b9 488d85e0feff. lea rax, [local_120h] +| | 0x004012c0 4889c7 mov rdi, rax +| | 0x004012c3 e8e8f9ffff call sym.imp.strdup ; char *strdup(const char *src) +| | 0x004012c8 488905494e20. mov qword str.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789, rax ; [0x606118:8]=0x404508 str.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +| | ; JMP XREF from 0x0040123f (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `-> 0x004012cf bffb454000 mov edi, str.bruteforce_message_pattern: ; 0x4045fb ; "bruteforce message pattern:" +| 0x004012d4 e8f7f8ffff call sym.imp.puts ; int puts(const char *s) +| 0x004012d9 be00040000 mov esi, 0x400 ; 1024 +| 0x004012de bfc0616000 mov edi, 0x6061c0 +| 0x004012e3 e836fcffff call sub.read_f1e ; ssize_t read(int fildes, void *buf, size_t nbyte) +| 0x004012e8 bfc0616000 mov edi, 0x6061c0 +| 0x004012ed e85ef9ffff call sym.imp.strlen ; size_t strlen(const char *s) +| 0x004012f2 8905a84e2000 mov dword [0x006061a0], eax ; [0x6061a0:4]=0 +| 0x004012f8 c785dcfeffff. mov dword [local_124h], 0 +| ; JMP XREF from 0x00401334 (sub.FlexMD5_bruteforce_tool_V0.1_148) +| .-> 0x00401302 8b85dcfeffff mov eax, dword [local_124h] +| : 0x00401308 4863d8 movsxd rbx, eax +| : 0x0040130b bfc0616000 mov edi, 0x6061c0 +| : 0x00401310 e83bf9ffff call sym.imp.strlen ; size_t strlen(const char *s) +| : 0x00401315 4839c3 cmp rbx, rax +| ,==< 0x00401318 731d jae 0x401337 +| |: 0x0040131a 8b85dcfeffff mov eax, dword [local_124h] +| |: 0x00401320 4898 cdqe +| |: 0x00401322 0fb680c06160. movzx eax, byte [rax + 0x6061c0] ; [0x6061c0:1]=0 +| |: 0x00401329 3c2e cmp al, 0x2e ; '.' ; 46 +| ,===< 0x0040132b 7409 je 0x401336 +| ||: 0x0040132d 8385dcfeffff. add dword [local_124h], 1 +| ||`=< 0x00401334 ebcc jmp 0x401302 +| || ; JMP XREF from 0x0040132b (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `---> 0x00401336 90 nop +| | ; JMP XREF from 0x00401318 (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `--> 0x00401337 8b85dcfeffff mov eax, dword [local_124h] +| 0x0040133d 4863d8 movsxd rbx, eax +| 0x00401340 bfc0616000 mov edi, 0x6061c0 +| 0x00401345 e806f9ffff call sym.imp.strlen ; size_t strlen(const char *s) +| 0x0040134a 4839c3 cmp rbx, rax +| ,=< 0x0040134d 7522 jne 0x401371 +| | 0x0040134f bf04000000 mov edi, 4 +| | 0x00401354 e877f9ffff call sym.imp.__cxa_allocate_exception +| | 0x00401359 c70000000000 mov dword [rax], 0 +| | 0x0040135f ba00000000 mov edx, 0 +| | 0x00401364 be70616000 mov esi, obj.typeinfoforint ; 0x606170 +| | 0x00401369 4889c7 mov rdi, rax +| | 0x0040136c e87ff9ffff call sym.imp.__cxa_throw +| | ; JMP XREF from 0x0040134d (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `-> 0x00401371 bf17464000 mov edi, str.md5_pattern: ; 0x404617 ; "md5 pattern:" +| 0x00401376 e855f8ffff call sym.imp.puts ; int puts(const char *s) +| 0x0040137b be21000000 mov esi, 0x21 ; '!' ; 33 +| 0x00401380 bfc0656000 mov edi, 0x6065c0 +| 0x00401385 e8ecfaffff call sub.read_e76 ; ssize_t read(int fildes, void *buf, size_t nbyte) +| 0x0040138a b800000000 mov eax, 0 +| 0x0040138f 488b4de8 mov rcx, qword [local_18h] +| 0x00401393 6448330c2528. xor rcx, qword fs:[0x28] +| ,=< 0x0040139c 7405 je 0x4013a3 +| | 0x0040139e e81df9ffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void) +| | ; JMP XREF from 0x0040139c (sub.FlexMD5_bruteforce_tool_V0.1_148) +| `-> 0x004013a3 4881c4280100. add rsp, 0x128 +| 0x004013aa 5b pop rbx +| 0x004013ab 5d pop rbp +\ 0x004013ac c3 ret +``` + +在 `0x004012b4` 下断点,以检查溢出点: +``` +gdb-peda$ x/s $rbp +0x7fffffffe3f0: "5A%KA%gA%6A%" +gdb-peda$ pattern_offset 5A%KA%gA%6A% +5A%KA%gA%6A% found at offset: 288 +``` +所以 rbp 的地址为 `288 / 8 = 36`。 + +找到 libc 的 `do_system` 函数里的 one\_gadget\_rce,地址为 `0x00041ee7`: +``` +| 0x00041ee7 488b056aff36. mov rax, qword [0x003b1e58] ; [0x3b1e58:8]=0 +| 0x00041eee 488d3d409313. lea rdi, str._bin_sh ; 0x17b235 ; "/bin/sh" +| 0x00041ef5 c70521253700. mov dword [obj.lock_4], 0 ; [0x3b4420:4]=0 +| 0x00041eff c7051b253700. mov dword [obj.sa_refcntr], 0 ; [0x3b4424:4]=0 +| 0x00041f09 488d742430 lea rsi, [local_30h] ; sym.lm_cache ; 0x30 +| 0x00041f0e 488b10 mov rdx, qword [rax] +| 0x00041f11 67e8c9260800 call sym.execve +``` + +#### Exploit +完整的 exp 如下: +```python + +``` ## 参考资料 +- [Shanghai-DCTF-2017 线下攻防Pwn题](https://www.anquanke.com/post/id/89855)