본문 바로가기

워게임/protostar

net3

#include "../common/common.c"


#define NAME "net3"

#define UID 996

#define GID 996

#define PORT 2996


/*

* Extract a null terminated string from the buffer 

*/


int get_string(char **result, unsigned char *buffer, u_int16_t len)

{

unsigned char byte;


byte = *buffer;


if(byte > len) errx(1, "badly formed packet");

*result = malloc(byte);

strcpy(*result, buffer + 1);


return byte + 1;

}


/*

* Check to see if we can log into the host

*/


int login(unsigned char *buffer, u_int16_t len)

{

char *resource, *username, *password;

int deduct;

int success;


if(len < 3) errx(1, "invalid login packet length");


resource = username = password = NULL;


deduct = get_string(&resource, buffer, len);

deduct += get_string(&username, buffer+deduct, len-deduct);

deduct += get_string(&password, buffer+deduct, len-deduct);


success = 0;

success |= strcmp(resource, "net3");

success |= strcmp(username, "awesomesauce");

success |= strcmp(password, "password");


free(resource);

free(username);

free(password);


return ! success;

}


void send_string(int fd, unsigned char byte, char *string)

{

struct iovec v[3];

u_int16_t len;

int expected;


len = ntohs(1 + strlen(string));


v[0].iov_base = &len;

v[0].iov_len = sizeof(len);


v[1].iov_base = &byte;

v[1].iov_len = 1;


v[2].iov_base = string;

v[2].iov_len = strlen(string);


expected = sizeof(len) + 1 + strlen(string);


if(writev(fd, v, 3) != expected) errx(1, "failed to write correct amount of bytes");


}


void run(int fd)

{

u_int16_t len;

unsigned char *buffer;

int loggedin;


while(1) {

nread(fd, &len, sizeof(len));

len = (len);

buffer = malloc(len);


if(! buffer) errx(1, "malloc failure for %d bytes", len);


nread(fd, buffer, len);


switch(buffer[0]) {

case 23: 

loggedin = login(buffer + 1, len - 1);

send_string(fd, 33, loggedin ? "successful" : "failed");

break;


default:

send_string(fd, 58, "what you talkin about willis?");

break;

}

}

}


int main(int argc, char **argv, char **envp)

{

int fd;

char *username;


/* Run the process as a daemon */

background_process(NAME, UID, GID); 


/* Wait for socket activity and return */

fd = serve_forever(PORT);


/* Set the client socket to STDIN, STDOUT, and STDERR */

set_io(fd);


/* Don't do this :> */

srandom(time(NULL));


run(fd);

}


이번엔 c소스로도 충분한 길이라서 ㅡㅡ; 그냥 이거 분석


일단 이번엔 유저로부터 2번 데이터를 입력받는다. 각각 데이터 사이즈, 실 데이터 뭐 이렇게 되는데..


일단 데이터에 어떠한 요소가 포함되어야하는지 보자.


우선 첫 번째 바이트는 무조건 23이 전송되야한다. 달리표현할 아스키도 없으니 걍 \x17보내면 될듯.


이제..문제가 되는부분이 get_string의 strcpy인데 스트링 파싱할때 null바이트로 구분하기때문에 이걸로 구분해줘야한다.


해줘야하는이유는 login 소스만봐도 알듯; 무튼


if(byte > len) errx(1, "badly formed packet");

*result = malloc(byte);


이것도 그렇고 음 버퍼에서 첫 바이트 검사해가지고 스트링 렝스랑 비교한다.


그럼 대강 페이로드는 "\x17", "\x05net3\x00", "\x0dawesomesauce\x00", "\x09password\x00" 이렇게 되겠네


길이를 맨 처음 보내야하는데 여기서 ntohs를 사용함. 이게 hex를 받아들여서 little endian으로 치환하는거니까 hex로 보


내함을 알 수 있음.


import socket, struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(('192.168.40.141', 2996))

payload = "\x17" + "\x05net3\x00" + "\x0dawesomesauce\x00" + "\x09password\x00"

len = struct.pack('>H', len(payload))

s.send(len)

s.send(payload)

print s.recv(1024)

s.close()


C:\Users\user>E:\pwnable\protostar\net3.py

 !successful


이렇게 풀림

'워게임 > protostar' 카테고리의 다른 글

net4  (0) 2015.11.04
net2  (0) 2015.11.04
net1  (0) 2015.11.04
net0  (0) 2015.11.04
format4  (0) 2015.11.03