#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
이렇게 풀림