반응형

이번 포스팅에서는 쉘을 실행시키는 간단한 C소스코드를 어셈블러로 바꿔보는 작업을 할 것입니다. 

이어서 다음 포스팅에서는 이번 포스팅에서 만든 코드를 토대로 크기를 줄여나가고 실제 사용하는 쉘코드에 흡사한 코드를 

만들어 내보도록 하겠습니다. 이하 존칭은 생략합니다.

참고로 이번 포스팅에서 사용한 방식은 AT&T방식이므로 혼동하지 않길 바란다.


우선 우리가 어셈블러 코드로 변환해볼 C코드는 이렇다.

다음과 같은 소스를 컴파일해 실행시켜보면 아래와 같이 쉘이 실행되는 것을 확인할 수 있다

(컴파일시 오류가 검출되긴 하나 프로그램 실행할때 문제가 되지 않는 오류이므로 실행파일이 생성된다)

위의 소스코드에서 왜 execve() 함수를 사용했다. 왜 execve()함수를 사용했을까?(의문을 가져야한다)

이유는 /usr/include/asm-i386/unistd.h 를 보면 알 수 있다. (해당 부분만 첨부하였다.)

밑줄을 그어논 부분을 보면 execve의 시스템콜 번호가 적혀있다. 왜 그런지 감이 오는가?

어셈블러로 해당 함수를 구현하면 다른 함수에 비해 코드를 적게 이용해도 되기 때문이다.

참고로, 이 함수는 바이너리 형태의 실행 파일이나 스크립트 파일을 실행시키는 함수이다. 

해당 함수의 자세한 사항이 궁금하다면 구글링을 해보도록..


이제부터 다시 위의 소스를 가져와서 어셈블러로 만드는 과정을 차근차근 짚어볼 것이다.



우리가 어셈블리어로 다음과 같은 소스를 구현하려면

1. 스택에 execve()를 실행하기 위한 인자들을 제대로 배치한다.

2. NULL과 인자값의 포인터를 스택에 넣는다.

3. 범용 레지스터에 이 값들의 위치를 지정해준다.

4. int  0x80을 호출하여 syscall 11을 호출하게 한다


<해당 사항을 적용한 1차 어셈블리 코드>

push $0x0    //NULL삽입

push 'sh\0'    // sh\0 문자열의 끝을 의미하는 \0

push '/bin' // /bin/문자열 위와 합쳐서 /bin/sh

mov %esp,%ebx  //현재의 스택포인터 :/bin/sh\0을 넣은지점

push $0x0  //NULL푸시

push %ebx // /bin/sh\0 포인터를 푸시

mov %esp,%ecx // esp레지스터는 /bin/sh\0 의 포인터다

mov $0x0,%edx // edx레지스터에 널을 삽입

mov %0xb,%eax //syscall 벡터 11번 지정 .eax에 삽입

int $0x80 // syscall을 호출하라는 인터럽트 발생 


이러한 코드를 만들어 내면 된다. 참고로 s\0과 /bin은 실제 어셈블리 코드가 아니라 추상화한 것이다. 실제로 넣을때는 아스키 코드 값으로 넣어줘야 하는데 변환해보면 

push $0x0068732f

push $0x6e69622f

다(little endian)

이 코드가 제대로 동작하는지 컴파일 해보자 

참고로 , 이 코드는 C프로그램 내에 인라인 어셈블로 코딩할 것이고 main()함수 안에 들어갈 것이기 때문에 함수의 프롤로그는 필요 없다.

하지만 아직 이 소스에 많은 문제점들이 남아 있다. 

이번 포스팅에서의 요점은 '해당 소스를 어셈블러로 구현할 수 있는가?' 이다. 

해당 소스를 외우지 말고 이해해서 만들 수 있는 정도가 되어야 한다.

자세한 사항은 다음 포스팅에서 설명하도록 하겠고, 이번포스팅은 여기서 마치도록 하겠다.

반응형
,