S!_Jmini 2020. 1. 7. 10:46

1. 왜 system 함수를 쓰지 않을까?

 

 

 shell을 따기위해서 system('/bin/sh') 를 호출해보았고

 

execve('/bin/sh',0,0) 도 호출해본 경험이 있다

 

그런데 왜 shellcode를 만들때는 execve( ) 를 사용하는 것일까?

 

 

 

 

일단 system 함수와 execve 함수가 실행되는 모습을 비교해보자

 

 

system.c 를 컴파일하여 실행한 모습

 

 

execve.c 를 컴파일하여 실행한 모습

 

 

 

위 두 모습을 비교해보면 system 함수는 호출된 뒤에 printf 도 호출했지만

 

execve가 호출되고 난 뒤에는 printf 가 호출되지 않았다

 

 

system 함수의 경우 작업이 끝날때까지 호출한 프로세스가 대기하다가 계속 수행되지만
execve 는 호출 프로세스가 바뀌어버린다는 차이가 있다

 

 

system 함수는 fork() 와 execve() 의 결합물이다

 

fork( ) 를 통해 자식 프로세스를 만들고,

 

자식 프로세스는 execve( ) 에 의해 흐름이 바뀌게 된다

 

하지만 부모프로세스는 현 상태를 유지하기 때문에

 

다음 작업을 계속 수행해 나갈 수 있다.

 

 

따라서 system 함수는 결국 execve( ) 를 좀 더 편하게 사용하는 함수인 것이다

 

 

 

 

 

 

2. 왜 asm 코드로 작성할까?

 

 

shellcode 도 execve( ) 를 호출한 코드의 hex 값인데

 

왜 c언어로 짠 코드를 dump 시켜서 사용하지 않는 것인지에 대해서 의문이 생겼다 

 

 

먼저 c로 컴파일한 파일을 objdump 명령어로 disassemble 해보자

 

execve.c

 

 

objdump -d execve

 

위에 출력되는 값 이외에도 많은 함수들이 로드되어 쉘코드의 길이가 왕창 길어진다

 

하지만 asm 코드로 작성한 파일은 c로 작성한 코드보다 쓸데없는 함수들의 로드가 이루어지지 않아

 

메모리가 작을 수 밖에 없고 따라서 쉘코드의 길이도 짧아질 수 밖에 없다

 

 

 

 

3. pwntool을 사용하여 shellcode 작성해보기

* stack 영역에 실행권한 주기

-z execstack

 

* Canary 해제하기

-fno-stack-protector

 

target binary

 

 

exploit code

 

 

간단하게 설명하자면 

 

execve의 첫번째 인자인 rdi 에 /bin/sh\x00 문자열을 가르키게 한다

 

execve의 두번째 인자인 rsi 를 0으로 만든다

 

execve의 세번째 인자인 rdx 를 0으로 만든다

 

execve를 호출하기 위해 rax에 59를 세팅해두고 syscall을 부르면

(syscall table 참조)

 

execve('/bin/sh',0,0) 이 실행된다

 

 

 

result

 

 

* 2020-07-04 c언어에서 inline asm으로 작성해봄!

#include <stdio.h>
int main(){

        printf("start!\n");


        __asm__ __volatile__(
                "mov $0x0068732f6E69622f, %rax\n\t"
                "push %rax\n\t"
                "mov %rsp, %rdi\n\t"
                "xor %rsi, %rsi\n\t"
                "xor %rdx, %rdx\n\t"
                "mov $0x3b, %rax\n\t"
                "syscall\n\t"
        );


        printf("end!\n");
        return 0;

}

 

 

어셈블리어 코딩을 위한 명령어

 

* sudo apt-get install gcc nasm

 

[ 오브젝트 파일 생성]

(32비트) nasm -f elf 파일명.asm

(64비트) nasm -f elf64 파일명.asm

 

[ 실행파일 생성 ]

ld 파일명.o -o 결과물파일명