systemhacking/practice

lob golem->darkknight (1바이트변조)

qkqhxla1 2015. 1. 21. 19:09

소스를 보면 strncpy로 1바이트만 변조 가능하다. (참조 http://turtle1000.tistory.com/47)

여기서는 어셈블리어 leave와 ret에 대해서 알아야 한다고 한다.

#include <stdio.h>


int main()

{

        printf("Hello world\n");

        return 0;

}

와 같이 간단한 프로그램을 만들고 컴파일한다. 이 파일을 gdb로 열고, 브레이크 포인트를

각각 leave,ret에 잡는다.



잡고 실행을 해서 leave와 ret의 동작을 알아보자. 







r `python -c 'print "A"*40+"\x40"'`

와 같이 실행해서, 40개를 아무거나 채워넣고, 변조하려는 부분을 \x40으로 채워넣고 실행해보면

첫번째 브레이크포인트에서 걸리는데, 간단한 hello world만을 출력한 프로그램이라 초반의 

mov %esp,%ebp한 부분 이외에 레지스터를 건드리는 부분이 없어서 info reg ebp esp eip로 세개의 레지스터를 출력해봤을때 esp와 ebp가 동일함을 알 수 있다. 첫번째 브레이크포인트는 leave명령어를 실행하기 전이다. c를 누르면 leave를 실행하고 그 다음줄의 ret를 실행하기 이전에 멈춘다. 이 상태에서 또다시 info reg ebp esp eip로 레지스터들을 출력해보면, 위처럼 나온다. 난 위에 써놓은 예제를 그대로 가져왔는데 이건 설명하기에 별로 안 좋은 예제 같다. 

일단 먼저 설명하자면 링크건 사이트의 주인장은

leave: mov esp, ebp -> pop ebp

ret: pop eip -> jmp eip

라고 써놓았는데.. 이건 인텔 문법이다. (gdb의 at&t문법으로 쓰자면 mov %ebp, %esp; pop %ebp정도 될듯)고로 leave명령어는 ebp를 esp로 옮기고 ebp를 pop한다는 뜻이다. 위의 실행 전의 esp값은 ebp와 같으므로 mov %ebp, %esp하나마나 똑같다.(이건 at&t문법 gdb문법) 거기에 pop ebp를 함으로서 esp가 4 증가한 값인 0xbffffb0c가 된다. 

leave와 ret는 외워두고, 지금 gdb는 종료하자.





이제 cp darkknight.c darkknigh1.c로 복사 후 darkknigh1로 컴파일 후 gdb로 darkknigh1을 실행해보자. 똑같이 leave, ret에 브레이크포인트를 걸고 r `python -c 'print "a"*40+"\x40"'` 로 실행해보자. 브레이크포인트1(leave실행전)에서 info reg ebp esp eip로 레지스터들을 살펴보면 darkknigh1프로그램은 중간에 많은 동작을 하므로 위의 테스팅용 hello world를 출력하는 프로그램과는 다르게 ebp와 esp가 변경되어 다른 값을 갖는것을 알 수 있다. 그리고 우리가 변조하기 위해 입력한 값(\x40)이 0xbffffaec주소 (가장 오른쪽 빨간색 네모부분)에 들어가 있는걸 확인할수 있다. 0xbffffa40은 ebp의 값이며, 우리가 끝에 입력한 \x40으로 인해 ebp의 끝부분 주소가 40으로 변조되었다. 끝에 들어간 이유는 리틀 엔디안이기 때문에 오른쪽부터 두개씩 들어간다. 예로 위의 0xbffffac0주소에는 90이 들어가있고, 0xbffffac1에는 01이, 0xbffffac2에는 00, 0xbfffac3에도 역시 00이 들어가있다. 마찬가지로 0xbffffac4는 빨간색 네모의 61이다.

우리가 변조 가능한 ebp는 0xbffffaㅁㅁ 두자리이며 이 주자리를 버퍼 관련 주소로 잘 조절하면 우리가 버퍼에 쉘코드를 집어넣었을때 쉘이 실행될것이다. 




여기서 잠깐 leave명령어 동작도 확인해보자. leave명령어는 at&t문법으로 mov %ebp, %esp; pop ebp이므로 살펴보면 ebp인 0xbffffa40을 esp로 옮기고, pop ebp명령어로 인해 esp값이 4 증가했다(0xbffffa44) ebp는 pop되므로 쓰레기값이 들어가는것같다(이건 맞는지 잘 모르겠음.). leave명령어가 잘 됨도 확인했다. 



gdb를 종료후 복사해둔 darkknight1.c 에 dumpcode를 넣고, 함수 안에 dumpcode명령어도 buffer의 주소를 출력하도록 넣은 후 컴파일해서 gdb로 위와 동일한 브레이크포인트를 걸어서 다시 실행해보자.


버퍼의 주소는 0xbffffac4이다. ebp주소를 변조하면 ret는 자동으로 ebp+4주소로 변조된다고 하였다. 아무거나 40개+\xc0를 넣으면 ebp가 0xbffffac0로 끝부분이 c0로 변조되고, 위에서 말했듯이 ret는 ebp+4의 주소로 변조되어 0xbffffac4가 된다. 즉 버퍼의 시작주소이다. 하지만 0xbffffac4주소. 즉 버퍼의 시작부분에 바로 쉘코드를 넣으면 안된다. ret는 버퍼에 쉘코드를 \x31\xc0\x31\xd2 처럼 들어갔을시 바로 해석하지 않고, 저 주소로 가야겠다고 생각한다. 한번 더 참조하는것이다. 그러므로 주소를 4바이트 뒤 주소를 적어놓고 4바이트 뒤에 쉘코드를 집어넣으면 잘 해석할것이다.

4바이트 뒤의주소(0xbffffac8)+쉘코드25바이트+아무거나11바이트+변조할바이트(0xc0)

./darkknigh1 `python -c 'print "\xc8\xfa\xff\xbf"+"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"+"\x90"*11+"\xc0"'`

처럼 하면 쉘이 주어짐을 확인할 수 있다. 이제 진짜 darkknight에 그대로 공격하면 된다.

'systemhacking > practice' 카테고리의 다른 글

lob bugbear->giant (rtl2)  (0) 2015.01.26
lob darkknight->bugbear  (0) 2015.01.22
lob skeleton->goelm (LD_PRELOAD)  (0) 2015.01.18
lob vampire->skeleton  (0) 2015.01.17
lob orge->troll  (0) 2015.01.15