Initial commit

This commit is contained in:
2025-04-12 08:26:23 +08:00
commit aa66855054
57 changed files with 1702 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
exit
exit
exit
+2
View File
@@ -0,0 +1,2 @@
sdb
*.o
+18
View File
@@ -0,0 +1,18 @@
.PHONY: all debug clean test
all: sdb
sdb: $(patsubst %.c,%.o,$(wildcard *.c))
gcc -o $@ $^ -lcapstone -std=gnu17 -g -fsanitize=address,undefined -fanalyzer
%.o: %.c
gcc -o $@ -c $^ -std=gnu17 -Wall -Wextra \
-g -fsanitize=address,undefined -fanalyzer \
-Wno-unused-value #-DDEBUG
clean:
- rm -f sdb *.o
make -C test clean
test: sdb
make -C test_case
BIN
View File
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <stdio.h>
#include <unistd.h>
#define ANSI_ESC_RED "\x1B[31m"
#define ANSI_ESC_GREEN "\x1B[32m"
#define ANSI_ESC_YELLOW "\x1B[33m"
#define ANSI_ESC_BLUE "\x1B[34m"
#define ANSI_ESC_MAGENTA "\x1B[35m"
#define ANSI_ESC_CYAN "\x1B[36m"
#define ANSI_ESC_COLOR_RESET "\x1B[m"
#define ANSI_ESC_CLEAR "\x1B[2J"
#define ANSI_ESC_CURSOR_RESET "\x1B[;H"
#ifdef DEBUG
#define PRINT(file, color, prompt, format, ...) \
fprintf(file, "%s%s", color, prompt), \
fprintf(file, format, ##__VA_ARGS__), \
fprintf(file, "%s", ANSI_ESC_COLOR_RESET)
#define ERROR(format, ...) \
PRINT(stderr, ANSI_ESC_RED, "[ERROR] ", format, ##__VA_ARGS__)
#define DEBUG(format, ...) \
PRINT(stderr, ANSI_ESC_YELLOW, "[DEBUG] ", format, ##__VA_ARGS__)
#else
#define PRINT(file, color, prompt, format, ...) \
fprintf(file, "%s", prompt), \
fprintf(file, format, ##__VA_ARGS__)
#define ERROR(format, ...)
#define DEBUG(format, ...)
#endif
#define INFO(format, ...) \
PRINT(stdout, ANSI_ESC_CYAN, "** ", format, ##__VA_ARGS__)
#define OUTPUT(format, ...) \
PRINT(stdout, ANSI_ESC_COLOR_RESET, "", format, ##__VA_ARGS__)
+116
View File
@@ -0,0 +1,116 @@
#include "sdb.h"
#include "vector.h"
#include "logger.h"
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/limits.h>
static inline enum instruction prompt(void)
{
static char *input;
static size_t input_len;
OUTPUT("(sdb) ");
getline(&input, &input_len, stdin);
char *op = strtok(input, " \t\n");
if (op == NULL) return INST_NOP;
if (strcmp(op, "exit") == 0) return INST_EXIT;
if (strcmp(op, "load") == 0) return INST_LOAD;
if (strcmp(op, "show") == 0) return INST_SHOW;
if (strcmp(op, "info") == 0) return INST_INFO;
if (strcmp(op, "break") == 0) return INST_BREAK;
if (strcmp(op, "delete") == 0) return INST_DELETE;
if (strcmp(op, "patch") == 0) return INST_PATCH;
if (strcmp(op, "si") == 0) return INST_SI;
if (strcmp(op, "cont") == 0) return INST_CONT;
if (strcmp(op, "syscall") == 0) return INST_SYSCALL;
return INST_INVALID;
}
int main(int argc, char *argv[])
{
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
char *filename = "";
if (argc > 1) {
filename = malloc(strlen(argv[1]) + 1);
strcpy(filename, argv[1]);
if (access(filename, F_OK) != 0) {
perror("main file open");
exit(1);
}
}
if (access(filename, F_OK) != 0) {
load_retry:
enum instruction op = prompt();
switch (op) {
case INST_NOP:
goto load_retry;
case INST_EXIT:
goto exit;
case INST_LOAD:
inst_load(&filename);
if (access(filename, F_OK) == 0)
break;
else {
INFO("file invalid\n");
goto load_retry;
}
default:
INFO("please load a program first.\n");
goto load_retry;
}
}
DEBUG("filename = %s\n", filename);
run(filename);
sync_regs();
disassemble_addr = regs.rip;
disassemble();
for (;;) {
enum instruction op = prompt();
DEBUG("op = 0x%x\n", (int)op);
switch (op) {
case INST_NOP: break;
case INST_EXIT: goto exit;
case INST_SHOW: disassemble(); break;
case INST_INFO: inst_info(); break;
case INST_BREAK: inst_break(); break;
case INST_DELETE: inst_delete(); break;
case INST_PATCH: inst_patch(); break;
case INST_SI: inst_si(); disassemble(); break;
case INST_CONT: inst_cont(); disassemble(); break;
case INST_SYSCALL: inst_syscall(); disassemble(); break;
default:
INFO("invalid command\n");
}
DEBUG("disassemble_addr = %p\n", (void *)disassemble_addr);
if (disassemble_addr == 0x00)
goto exit;
}
exit:
free(filename);
free(bps);
return 0;
}
+410
View File
@@ -0,0 +1,410 @@
#include "sdb.h"
#include "logger.h"
#include "vector.h"
#include <stdlib.h>
#include <string.h>
#include <capstone/capstone.h>
#include <sys/user.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
int child;
int status;
struct user_regs_struct regs;
uint64_t disassemble_addr;
long syscall_nr = 0xffff;
void sync_regs(void)
{
if (ptrace(PTRACE_GETREGS, child, NULL, &regs) != 0) {
ERROR("sync_regs ptrace getregs\n");
perror("sync_regs");
exit(1);
}
}
uint8_t poke(uint64_t addr, uint8_t data)
{
uint64_t ret = ptrace(PTRACE_PEEKTEXT, child, addr, NULL);
ptrace(PTRACE_POKETEXT, child, addr, (ret & ~0xff) | data);
return ret & 0xff;
}
void run(const char *filename)
{
child = fork();
if (child < 0) {
ERROR("run fork failed\n");
perror("run fork");
exit(1);
}
if (child == 0) {
DEBUG("forked\n");
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
perror("run traceme");
exit(1);
}
execl(filename, filename, NULL);
perror("run execl");
}
if (waitpid(child, &status, 0) < 0) {
perror("run waitpid");
exit(1);
}
if (WIFSTOPPED(status) == 0) {
perror("run stopped");
exit(1);
}
ptrace(PTRACE_SETOPTIONS, child, 0,
PTRACE_O_EXITKILL | PTRACE_O_TRACESYSGOOD);
sync_regs();
INFO("program '%s' loaded. entry point %p.\n", filename, (void *)regs.rip);
}
void disassemble()
{
if (disassemble_addr == 0x00) return;
const uint64_t rip = disassemble_addr;
long ret;
uint8_t code[64], *ptr = (uint8_t *)&ret;
for (int i = 0; i < 8; i++) {
ret = ptrace(PTRACE_PEEKTEXT, child, rip + (i << 3), NULL);
for (int j = 0; j < 8; j++)
code[i << 3 | j] = ptr[j];
// DEBUG("\n");
}
for (int i = 0; i < bps_len; i++)
if (bps[i].addr && rip <= bps[i].addr && bps[i].addr < rip + 64)
code[bps[i].addr - rip] = bps[i].data;
csh handle;
if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {
perror("disassemble cs_open");
exit(1);
}
cs_insn *insn;
int count = cs_disasm(handle, code, sizeof(code) - 1, rip, 0, &insn);
if (count > 0) {
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
if (insn[i].size == 2 &&
insn[i].bytes[0] == 0 &&
insn[i].bytes[1] == 0) {
INFO("the address is out of the range of the text section.\n");
break;
}
OUTPUT("%12lx: ", insn[i].address);
char insn_buf[25] = "", *insn_buf_ptr = insn_buf;
for (int j = 0; j < insn[i].size; j++)
insn_buf_ptr += sprintf(insn_buf_ptr, "%02x ",
(uint8_t)insn[i].bytes[j]);
OUTPUT("%-24s%-10s %s\n", insn_buf, insn[i].mnemonic, insn[i].op_str);
}
cs_free(insn, count);
} else {
perror("disassemble");
exit(1);
}
cs_close(&handle);
}
void inst_load(char **filename)
{
char *token = strtok(NULL, " \t\n");
if (token == NULL) {
perror("inst_load");
disassemble_addr = 0x00;
return;
}
*filename = malloc(strlen(token) + 1);
strcpy(*filename, token);
}
void inst_si(void)
{
if (!WIFSTOPPED(status)) {
ERROR("program not running.\n");
perror("inst_si not running");
disassemble_addr = 0x00;
return;
}
syscall_nr = 0xffff;
sync_regs();
uint64_t rip = regs.rip;
DEBUG("rip = %lx\n", rip);
const struct bps_node *bp = find(rip);
if (bp)
poke(bp->addr, bp->data);
ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
waitpid(child, &status, 0);
if (bp)
poke(bp->addr, 0xcc);
sync_regs();
rip = regs.rip, bp = find(rip);
if (bp)
INFO("hit a breakpoint at %p.\n", (void *)rip);
if (!WIFSTOPPED(status)) {
INFO("the target program terminated.\n");
disassemble_addr = 0x00;
} else {
sync_regs();
disassemble_addr = regs.rip;
}
}
void inst_cont(void)
{
if (!WIFSTOPPED(status)) {
ERROR("program not running.\n");
perror("inst_cont not running");
exit(1);
}
syscall_nr = 0xffff;
sync_regs();
uint64_t rip = regs.rip;
DEBUG("rip = %lx\n", rip);
const struct bps_node *bp = find(rip);
if (bp) {
poke(bp->addr, bp->data);
ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
waitpid(child, &status, 0);
poke(bp->addr, 0xcc);
}
ptrace(PTRACE_CONT, child, NULL, NULL);
waitpid(child, &status, 0);
if (!WIFSTOPPED(status)) {
INFO("the target program terminated.\n");
disassemble_addr = 0x00;
} else {
sync_regs();
rip = regs.rip;
bp = find(rip - 1);
if (bp == NULL) {
perror("inst_cont bp = NULL\n");
exit(1);
}
INFO("hit a breakpoint at %p.\n", (void *)(rip - 1));
poke(bp->addr, bp->data);
regs.rip -= 1;
ptrace(PTRACE_SETREGS, child, 0, &regs);
poke(bp->addr, 0xcc);
sync_regs();
disassemble_addr = regs.rip;
}
}
void inst_info(void)
{
char *op = strtok(NULL, " \t\n");
if (op == NULL)
goto inst_info_invalid;
if (strcmp(op, "reg") == 0)
inst_info_reg();
else if (strcmp(op, "break") == 0)
inst_info_break();
else
goto inst_info_invalid;
return;
inst_info_invalid:
ERROR("invalid command\n");
INFO("Command: info [reg | break]\n");
}
void inst_info_reg(void)
{
sync_regs();
#define OUTPUT_REGS(a, b, c) \
OUTPUT("$%-7s 0x%016lx\t$%-7s 0x%016lx\t$%-7s 0x%016lx\n", \
#a, (unsigned long)regs.a, \
#b, (unsigned long)regs.b, \
#c, (unsigned long)regs.c)
OUTPUT_REGS(rax, rbx, rcx);
OUTPUT_REGS(rdx, rsi, rdi);
OUTPUT_REGS(rbp, rsp, r8);
OUTPUT_REGS( r9, r10, r11);
OUTPUT_REGS(r12, r13, r14);
OUTPUT_REGS(r15, rip, eflags);
#undef OUTPUT_REGS
}
void inst_info_break(void)
{
if (bps_cnt == 0) {
INFO("no breakpoints.\n");
return;
}
OUTPUT("%-6s\t%-12s\n", "Num", "Address");
for (int i = 0; i < bps_len; i++)
if (bps[i].addr)
OUTPUT("%-6d\t0x%lx\n", i, bps[i].addr);
}
void inst_break(void)
{
char *token = strtok(NULL, " \t\n");
if (token == NULL) {
ERROR("invalid command.\n");
INFO("Command: break [hex address]\n");
return;
}
uint64_t addr;
sscanf(token, "%lx", &addr);
bps_push(addr, poke(addr, 0xcc));
INFO("set a breakpoint at %p.\n", (void *)addr);
}
void inst_delete(void)
{
char *token = strtok(NULL, " \t\n");
if (token == NULL) {
ERROR("invalid command.\n");
INFO("Command: delete [id]\n");
return;
}
int id;
sscanf(token, "%d", &id);
if (bps_len <= id || bps[id].addr == 0x00)
INFO("breakpoint %d does not exist.\n", id);
else {
poke(bps[id].addr, bps[id].data);
bps[id].addr = 0x00, bps_cnt--;
INFO("delete breakpoint %d.\n", id);
}
}
void inst_patch(void)
{
char *token = strtok(NULL, " \t\n");
if (token == NULL) goto inst_patch_invalid;
uint64_t addr;
sscanf(token, "%lx", &addr);
token = strtok(NULL, " \t\n");
if (token == NULL) goto inst_patch_invalid;
uint64_t data;
sscanf(token, "%lx", &data);
token = strtok(NULL, " \t\n");
if (token == NULL) goto inst_patch_invalid;
int len;
sscanf(token, "%d", &len);
uint64_t val = ptrace(PTRACE_PEEKTEXT, child, addr, NULL);
DEBUG("original val = %lx\n", val);
uint64_t mask = ((uint64_t)1 << (len << 3)) - 1;
DEBUG("mask = %lx\n", mask);
val = (val & ~mask) | (data & mask);
DEBUG("modified val = %lx\n", val);
for (int i = 0; i < bps_len; i++)
if (bps[i].addr && addr <= bps[i].addr && bps[i].addr < addr + len) {
int j = bps[i].addr - addr;
bps[i].data = (data >> j) & 0xff;
}
if (ptrace(PTRACE_POKETEXT, child, addr, val) != 0) {
ERROR("inst_patch POKETEXT\n");
perror("inst_patch ptrace");
exit(1);
}
INFO("patch memory at address 0x%lx.\n", addr);
return;
inst_patch_invalid:
ERROR("invalid command.\n");
INFO("Command: patch [hex address] [hex value] [len]\n");
}
void inst_syscall(void)
{
if (!WIFSTOPPED(status)) {
ERROR("program not running.\n");
perror("inst_syscall");
disassemble_addr = 0x00;
return;
}
sync_regs();
uint64_t rip = regs.rip;
const struct bps_node *bp = find(rip);
if (bp) {
poke(bp->addr, bp->data);
ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
waitpid(child, &status, 0);
poke(bp->addr, 0xcc);
}
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
waitpid(child, &status, 0);
if (!WIFSTOPPED(status)) {
INFO("the target program terminated.\n");
disassemble_addr = 0x00;
} else {
sync_regs();
rip = regs.rip;
DEBUG("rip = %p\n", (void *)rip);
if (WSTOPSIG(status) & 0x80) {
if (syscall_nr == 0xffff) {
syscall_nr = regs.orig_rax;
INFO("enter a syscall(%ld) at %p.\n",
syscall_nr, (void *)(rip - 2));
} else {
INFO("leave a syscall(%ld) = %llu at %p.\n",
syscall_nr, regs.rax, (void *)(rip - 2));
syscall_nr = 0xffff;
}
disassemble_addr = regs.rip - 2;
return;
}
bp = find(rip - 1);
if (bp == NULL) {
ERROR("inst_syscall bp = NULL\n");
perror("inst_syscall");
exit(1);
}
INFO("hit a breakpoint at %p.\n", (void *)(rip - 1));
poke(bp->addr, bp->data);
regs.rip -= 1;
ptrace(PTRACE_SETREGS, child, 0, &regs);
poke(bp->addr, 0xcc);
disassemble_addr = regs.rip;
}
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/user.h>
#define INSTRUCTION_COUNT 5
enum instruction {
INST_NOP = 0x00,
INST_EXIT = 0x01,
INST_LOAD = 0x02,
INST_SHOW = 0x10,
INST_INFO = 0x11,
INST_BREAK = 0x20,
INST_DELETE = 0x21,
INST_PATCH = 0x22,
INST_SI = 0x30,
INST_CONT = 0x31,
INST_SYSCALL = 0x32,
INST_INVALID = 0xff,
};
void sync_regs(void);
uint8_t poke(uint64_t addr, uint8_t data);
void run(const char *filename);
void disassemble();
void inst_load(char **filename);
void inst_si(void);
void inst_cont(void);
void inst_info(void);
void inst_info_reg(void);
void inst_info_break(void);
void inst_break(void);
void inst_delete(void);
void inst_patch(void);
void inst_syscall(void);
extern int child;
extern int status;
extern struct user_regs_struct regs;
extern uint64_t disassemble_addr;
extern long syscall_nr;
BIN
View File
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
(sdb) si
** please load a program first.
(sdb) load ./hello
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
(sdb) si
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
(sdb) si
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401017: bf 01 00 00 00 mov edi, 1
(sdb) cont
hello world!
** the target program terminated.
+6
View File
@@ -0,0 +1,6 @@
./sdb
si
load ./hello
si
si
cont
+44
View File
@@ -0,0 +1,44 @@
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
(sdb) break 0x401005
** set a breakpoint at 0x401005.
(sdb) break 40102b
** set a breakpoint at 0x40102b.
(sdb) info break
Num Address
0 0x401005
1 0x40102b
(sdb) si
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
(sdb) si
** hit a breakpoint at 0x401005.
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401017: bf 01 00 00 00 mov edi, 1
(sdb) cont
** hit a breakpoint at 0x40102b.
40102b: b8 01 00 00 00 mov eax, 1
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
(sdb) info reg
$rax 0x0000000000402000 $rbx 0x0000000000000000 $rcx 0x0000000000000000
$rdx 0x000000000000000e $rsi 0x0000000000402000 $rdi 0x0000000000000001
$rbp 0x00007ffe0e5cd5b8 $rsp 0x00007ffe0e5cd5b0 $r8 0x0000000000000000
$r9 0x0000000000000000 $r10 0x0000000000000000 $r11 0x0000000000000000
$r12 0x0000000000000000 $r13 0x0000000000000000 $r14 0x0000000000000000
$r15 0x0000000000000000 $rip 0x000000000040102b $eflags 0x0000000000000202
(sdb) cont
hello world!
** the target program terminated.
+9
View File
@@ -0,0 +1,9 @@
./sdb ./hello
break 0x401005
break 40102b
info break
si
si
cont
info reg
cont
+49
View File
@@ -0,0 +1,49 @@
** program './guess' loaded. entry point 0x40108b.
40108b: f3 0f 1e fa endbr64
40108f: 55 push rbp
401090: 48 89 e5 mov rbp, rsp
401093: 48 83 ec 10 sub rsp, 0x10
401097: ba 12 00 00 00 mov edx, 0x12
(sdb) break 0x4010de
** set a breakpoint at 0x4010de.
(sdb) cont
guess a number > 1
** hit a breakpoint at 0x4010de.
4010de: 48 89 c7 mov rdi, rax
4010e1: e8 1a ff ff ff call 0x401000
4010e6: 85 c0 test eax, eax
4010e8: 75 1b jne 0x401105
4010ea: ba 06 00 00 00 mov edx, 6
(sdb) patch 0x4010e8 0x9090 2
** patch memory at address 0x4010e8.
(sdb) si
4010e1: e8 1a ff ff ff call 0x401000
4010e6: 85 c0 test eax, eax
4010e8: 90 nop
4010e9: 90 nop
4010ea: ba 06 00 00 00 mov edx, 6
(sdb) info break
Num Address
0 0x4010de
(sdb) delete 0
** delete breakpoint 0.
(sdb) break 0x4010ea
** set a breakpoint at 0x4010ea.
(sdb) delete 0
** breakpoint 0 does not exist.
(sdb) info break
Num Address
1 0x4010ea
(sdb) cont
** hit a breakpoint at 0x4010ea.
4010ea: ba 06 00 00 00 mov edx, 6
4010ef: 48 8d 05 1f 0f 00 00 lea rax, [rip + 0xf1f]
4010f6: 48 89 c6 mov rsi, rax
4010f9: bf 01 00 00 00 mov edi, 1
4010fe: e8 25 00 00 00 call 0x401128
(sdb) patch 0x402015 0x4e49570a 4
** patch memory at address 0x402015.
(sdb) cont
WIN
** the target program terminated.
+14
View File
@@ -0,0 +1,14 @@
./sdb ./guess
break 0x4010de
cont
1
patch 0x4010e8 0x9090 2
si
info break
delete 0
break 0x4010ea
delete 0
info break
cont
patch 0x402015 0x4e49570a 4
cont
+45
View File
@@ -0,0 +1,45 @@
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
(sdb) break 0x401005
** set a breakpoint at 0x401005.
(sdb) break 40102b
** set a breakpoint at 0x40102b.
(sdb) cont
** hit a breakpoint at 0x401005.
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401017: bf 01 00 00 00 mov edi, 1
(sdb) syscall
** hit a breakpoint at 0x40102b.
40102b: b8 01 00 00 00 mov eax, 1
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
(sdb) syscall
** enter a syscall(1) at 0x401030.
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
40103a: c3 ret
(sdb) syscall
hello world!
** leave a syscall(1) = 14 at 0x401030.
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
40103a: c3 ret
(sdb) syscall
** enter a syscall(60) at 0x401040.
401040: 0f 05 syscall
** the address is out of the range of the text section.
(sdb) syscall
** the target program terminated.
+9
View File
@@ -0,0 +1,9 @@
./sdb ./hello
break 0x401005
break 40102b
cont
syscall
syscall
syscall
syscall
syscall
+32
View File
@@ -0,0 +1,32 @@
** program './guess' loaded. entry point 0x40108b.
40108b: f3 0f 1e fa endbr64
40108f: 55 push rbp
401090: 48 89 e5 mov rbp, rsp
401093: 48 83 ec 10 sub rsp, 0x10
401097: ba 12 00 00 00 mov edx, 0x12
(sdb) patch 0x4010e8 0x9090 2
** patch memory at address 0x4010e8.
(sdb) break 0x4010e8
** set a breakpoint at 0x4010e8.
(sdb) cont
guess a number > 1
** hit a breakpoint at 0x4010e8.
4010e8: 90 nop
4010e9: 90 nop
4010ea: ba 06 00 00 00 mov edx, 6
4010ef: 48 8d 05 1f 0f 00 00 lea rax, [rip + 0xf1f]
4010f6: 48 89 c6 mov rsi, rax
(sdb) break 4010ea
** set a breakpoint at 0x4010ea.
(sdb) patch 4010ea 0x03ba 4
** patch memory at address 0x4010ea.
(sdb) cont
** hit a breakpoint at 0x4010ea.
4010ea: ba 03 00 00 00 mov edx, 3
4010ef: 48 8d 05 1f 0f 00 00 lea rax, [rip + 0xf1f]
4010f6: 48 89 c6 mov rsi, rax
4010f9: bf 01 00 00 00 mov edi, 1
4010fe: e8 25 00 00 00 call 0x401128
(sdb) cont
ye** the target program terminated.
+9
View File
@@ -0,0 +1,9 @@
./sdb ./guess
patch 0x4010e8 0x9090 2
break 0x4010e8
cont
1
break 4010ea
patch 4010ea 0x03ba 4
cont
cont
+27
View File
@@ -0,0 +1,27 @@
** program './guess' loaded. entry point 0x40108b.
40108b: f3 0f 1e fa endbr64
40108f: 55 push rbp
401090: 48 89 e5 mov rbp, rsp
401093: 48 83 ec 10 sub rsp, 0x10
401097: ba 12 00 00 00 mov edx, 0x12
(sdb) break 0x401128
** set a breakpoint at 0x401128.
(sdb) cont
** hit a breakpoint at 0x401128.
401128: b8 01 00 00 00 mov eax, 1
40112d: 0f 05 syscall
40112f: c3 ret
401130: b8 00 00 00 00 mov eax, 0
401135: 0f 05 syscall
(sdb) cont
guess a number > 1
** hit a breakpoint at 0x401128.
401128: b8 01 00 00 00 mov eax, 1
40112d: 0f 05 syscall
40112f: c3 ret
401130: b8 00 00 00 00 mov eax, 0
401135: 0f 05 syscall
(sdb) cont
no no no
** the target program terminated.
+6
View File
@@ -0,0 +1,6 @@
./sdb ./guess
break 0x401128
cont
cont
1
cont
+35
View File
@@ -0,0 +1,35 @@
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
(sdb) break 0x401030
** set a breakpoint at 0x401030.
(sdb) break 0x401040
** set a breakpoint at 0x401040.
(sdb) syscall
** hit a breakpoint at 0x401030.
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
40103a: c3 ret
(sdb) syscall
** enter a syscall(1) at 0x401030.
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
40103a: c3 ret
(sdb) cont
hello world!
** hit a breakpoint at 0x401040.
401040: 0f 05 syscall
** the address is out of the range of the text section.
(sdb) syscall
** enter a syscall(60) at 0x401040.
401040: 0f 05 syscall
** the address is out of the range of the text section.
(sdb) syscall
** the target program terminated.
+8
View File
@@ -0,0 +1,8 @@
./sdb ./hello
break 0x401030
break 0x401040
syscall
syscall
cont
syscall
syscall
+8
View File
@@ -0,0 +1,8 @@
all:
chmod +x run_examples.py guess hello
test: all
./run_examples.py
clean:
rm -f *.out diff.txt
Executable
BIN
View File
Binary file not shown.
Executable
BIN
View File
Binary file not shown.
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env python3
from typing import List
from pwn import process, context
context.log_level = "error"
cases_to_run = ["1", "2", "3", "4", "5", "6", "7"]
TIMEOUT_SECONDS = 0.01
def wrap_recvrepeat(r):
if r.poll() is not None:
return b""
return r.recvrepeat(TIMEOUT_SECONDS)
def recvrepeats(r):
output = wrap_recvrepeat(r)
while output == b"":
if r.poll() is not None:
break
output = wrap_recvrepeat(r)
ret = b""
while output != b"":
ret += output
output = wrap_recvrepeat(r)
return ret
def execute_process(
case: str, command: List[str], stdin: List[str]
) -> tuple[int, bytes]:
"""Returns the exit code and output of the process (including stdin and stderr)"""
print(f"Running case {case} with command: {command}")
try:
r = process(command, shell=False)
output = b""
for line in stdin:
ret = recvrepeats(r)
output += ret
output += line.encode("utf-8")
if r.poll() is None: # Only send if the process is still running
r.send(line.encode("utf-8"))
output += recvrepeats(r)
r.close()
except Exception as e:
print(f"Error: {e}")
return 1, b""
return 0, output
if __name__ == "__main__":
# Clean up the diff file
with open("diff.txt", "w") as f:
f.write("")
for case in cases_to_run:
with open(f"{case}.in", "r") as f:
lines = f.readlines()
run_command: List[str] = lines[0].split()
input = lines[1:]
_, output = execute_process(case, run_command, input)
# Remove the last prompt
if output.endswith(b"(sdb) "):
output = output[:-6]
# Remove null bytes
output = output.replace(b"\x00", b"")
# Write the output to a file
with open(f"{case}.out", "wb") as f:
f.write(output)
diff_command = f"diff -w -B -u {case}.out {case}.ans"
diff_process = process(diff_command, shell=True)
diff_output = diff_process.recvall()
diff_process.close()
diff_lines = diff_output.decode("utf-8").split("\n")
diff_lines = [
line for line in diff_lines if line.startswith("-") or line.startswith("+")
]
diff_lines = [line for line in diff_lines if not line.startswith("---")]
diff_lines = [line for line in diff_lines if not line.startswith("+++")]
i = 0
while True:
if i + 1 >= len(diff_lines):
break
if "-$rbp" in diff_lines[i] and "+$rbp" in diff_lines[i + 1]:
output_line = diff_lines.pop(i)[1:].split()
expected_line = diff_lines.pop(i)[1:].split()
if len(output_line) != 6:
diff_lines.append(f"error")
break
output_rbp = int(output_line[1], 16)
output_rsp = int(output_line[3], 16)
output_r8 = int(output_line[5], 16)
expected_rbp = int(expected_line[1], 16)
expected_rsp = int(expected_line[3], 16)
expected_r8 = int(expected_line[5], 16)
if (
output_rbp - output_rsp != expected_rbp - expected_rsp
or output_r8 != expected_r8
):
diff_lines.append(f"error")
break
continue
i += 1
# Print the diff output if there is a difference
print(f"Case {case}: {'PASS' if len(diff_lines) == 0 else 'FAIL'}", end="\n\n")
# Print the diff output to `diff.txt`
if len(diff_lines) > 0:
with open("diff.txt", "a") as f:
f.write(diff_output.decode("utf-8"))
f.write("\n\n")
+13
View File
@@ -0,0 +1,13 @@
.PHONY: all
all: ../sdb
python run.py 1
python run.py 2
python run.py 3
python run.py 4
python run.py h1
python run.py h2
python run.py h3
python run.py h4
python run.py h5
python run.py h6
Executable
BIN
View File
Binary file not shown.
Executable
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
../sdb
si
load ./hello
si
si
cont
+9
View File
@@ -0,0 +1,9 @@
../sdb ./hello
break 0x401005
break 40102b
info break
si
si
cont
info reg
cont
+14
View File
@@ -0,0 +1,14 @@
../sdb ./guess
break 0x4010de
cont
1
patch 0x4010e8 0x9090 2
si
info break
delete 0
break 0x4010ea
delete 0
info break
cont
patch 0x402015 0x4e49570a 4
cont
+9
View File
@@ -0,0 +1,9 @@
../sdb ./hello
break 0x401005
break 40102b
cont
syscall
syscall
syscall
syscall
syscall
+13
View File
@@ -0,0 +1,13 @@
../sdb ./game
break 401005
break 401009
info break
syscall
syscall
delete 0
cont
2
break 401005
info break
cont
2
+9
View File
@@ -0,0 +1,9 @@
../sdb ./game
break 401005
cont
patch 40101a 0x02f88348 4
cont
1
patch 40101a 0x01f88348 4
cont
1
+6
View File
@@ -0,0 +1,6 @@
../sdb
si
load ./deep
si
si
cont
+9
View File
@@ -0,0 +1,9 @@
../sdb ./deep
break 401136
break 40113d
info break
si
si
cont
info reg
cont
+12
View File
@@ -0,0 +1,12 @@
../sdb ./deep
break 40109c
info break
break 401031
info break
delete 0
info break
delete 3
info break
cont
info break
cont
+9
View File
@@ -0,0 +1,9 @@
../sdb ./game
break 0x4010f1
syscall
syscall
syscall
syscall
3
syscall
syscall
+19
View File
@@ -0,0 +1,19 @@
** please load a program first.
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401017: bf 01 00 00 00 mov edi, 1
hello world!
** the target program terminated.
+36
View File
@@ -0,0 +1,36 @@
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
** set a breakpoint at 0x401005.
** set a breakpoint at 0x40102b.
Num Address
0 0x401005
1 0x40102b
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
** hit a breakpoint at 0x401005.
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401017: bf 01 00 00 00 mov edi, 1
** hit a breakpoint at 0x40102b.
40102b: b8 01 00 00 00 mov eax, 1
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
$rax 0x0000000000402000 $rbx 0x0000000000000000 $rcx 0x0000000000000000
$rdx 0x000000000000000e $rsi 0x0000000000402000 $rdi 0x0000000000000001
$rbp 0x00007ffe0e5cd5b8 $rsp 0x00007ffe0e5cd5b0 $r8 0x0000000000000000
$r9 0x0000000000000000 $r10 0x0000000000000000 $r11 0x0000000000000000
$r12 0x0000000000000000 $r13 0x0000000000000000 $r14 0x0000000000000000
$r15 0x0000000000000000 $rip 0x000000000040102b $eflags 0x0000000000000202
hello world!
** the target program terminated.
+37
View File
@@ -0,0 +1,37 @@
** program './guess' loaded. entry point 0x40108b.
40108b: f3 0f 1e fa endbr64
40108f: 55 push rbp
401090: 48 89 e5 mov rbp, rsp
401093: 48 83 ec 10 sub rsp, 0x10
401097: ba 12 00 00 00 mov edx, 0x12
** set a breakpoint at 0x4010de.
guess a number >
** hit a breakpoint at 0x4010de.
4010de: 48 89 c7 mov rdi, rax
4010e1: e8 1a ff ff ff call 0x401000
4010e6: 85 c0 test eax, eax
4010e8: 75 1b jne 0x401105
4010ea: ba 06 00 00 00 mov edx, 6
** patch memory at address 0x4010e8.
4010e1: e8 1a ff ff ff call 0x401000
4010e6: 85 c0 test eax, eax
4010e8: 90 nop
4010e9: 90 nop
4010ea: ba 06 00 00 00 mov edx, 6
Num Address
0 0x4010de
** delete breakpoint 0.
** set a breakpoint at 0x4010ea.
** breakpoint 0 does not exist.
Num Address
1 0x4010ea
** hit a breakpoint at 0x4010ea.
4010ea: ba 06 00 00 00 mov edx, 6
4010ef: 48 8d 05 1f 0f 00 00 lea rax, [rip + 0xf1f]
4010f6: 48 89 c6 mov rsi, rax
4010f9: bf 01 00 00 00 mov edi, 1
4010fe: e8 25 00 00 00 call 0x401128
** patch memory at address 0x402015.
WIN
** the target program terminated.
+37
View File
@@ -0,0 +1,37 @@
** program './hello' loaded. entry point 0x401000.
401000: f3 0f 1e fa endbr64
401004: 55 push rbp
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
** set a breakpoint at 0x401005.
** set a breakpoint at 0x40102b.
** hit a breakpoint at 0x401005.
401005: 48 89 e5 mov rbp, rsp
401008: ba 0e 00 00 00 mov edx, 0xe
40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
401014: 48 89 c6 mov rsi, rax
401017: bf 01 00 00 00 mov edi, 1
** hit a breakpoint at 0x40102b.
40102b: b8 01 00 00 00 mov eax, 1
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
** enter a syscall(1) at 0x401030.
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
40103a: c3 ret
hello world!
** leave a syscall(1) = 14 at 0x401030.
401030: 0f 05 syscall
401032: c3 ret
401033: b8 00 00 00 00 mov eax, 0
401038: 0f 05 syscall
40103a: c3 ret
** enter a syscall(60) at 0x401040.
401040: 0f 05 syscall
** the address is out of the range of the text section.
** the target program terminated.
+44
View File
@@ -0,0 +1,44 @@
** program './game' loaded. entry point 0x401000.
401000: b9 05 00 00 00 mov ecx, 5
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
** set a breakpoint at 0x401005.
** set a breakpoint at 0x401009.
Num Address
0 0x401005
1 0x401009
** hit a breakpoint at 0x401005.
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
401015: e8 72 00 00 00 call 0x40108c
** hit a breakpoint at 0x401009.
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
401015: e8 72 00 00 00 call 0x40108c
40101a: 48 83 f8 01 cmp rax, 1
** delete breakpoint 0.
guess a number :
wrong
** hit a breakpoint at 0x401009.
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
401015: e8 72 00 00 00 call 0x40108c
40101a: 48 83 f8 01 cmp rax, 1
** set a breakpoint at 0x401005.
Num Address
1 0x401009
2 0x401005
guess a number :
wrong
** hit a breakpoint at 0x401005.
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
401015: e8 72 00 00 00 call 0x40108c
+26
View File
@@ -0,0 +1,26 @@
** program './game' loaded. entry point 0x401000.
401000: b9 05 00 00 00 mov ecx, 5
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
** set a breakpoint at 0x401005.
** hit a breakpoint at 0x401005.
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
401015: e8 72 00 00 00 call 0x40108c
** patch memory at address 0x40101a.
guess a number :
wrong
** hit a breakpoint at 0x401005.
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
401015: e8 72 00 00 00 call 0x40108c
** patch memory at address 0x40101a.
guess a number :
you win
** the target program terminated.
+21
View File
@@ -0,0 +1,21 @@
** please load a program first.
** program './deep' loaded. entry point 0x401131.
401131: f3 0f 1e fa endbr64
401135: 55 push rbp
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
401135: 55 push rbp
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
401142: e8 3f ff ff ff call 0x401086
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
401142: e8 3f ff ff ff call 0x401086
401147: 89 45 fc mov dword ptr [rbp - 4], eax
this is callee
hello world
hello unix
** the target program terminated.
+38
View File
@@ -0,0 +1,38 @@
** program './deep' loaded. entry point 0x401131.
401131: f3 0f 1e fa endbr64
401135: 55 push rbp
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
** set a breakpoint at 0x401136.
** set a breakpoint at 0x40113d.
Num Address
0 0x401136
1 0x40113d
401135: 55 push rbp
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
401142: e8 3f ff ff ff call 0x401086
** hit a breakpoint at 0x401136.
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
401142: e8 3f ff ff ff call 0x401086
401147: 89 45 fc mov dword ptr [rbp - 4], eax
** hit a breakpoint at 0x40113d.
40113d: b8 00 00 00 00 mov eax, 0
401142: e8 3f ff ff ff call 0x401086
401147: 89 45 fc mov dword ptr [rbp - 4], eax
40114a: b8 00 00 00 00 mov eax, 0
40114f: e8 5d ff ff ff call 0x4010b1
$rax 0x0000000000000000 $rbx 0x0000000000000000 $rcx 0x0000000000000000
$rdx 0x0000000000000000 $rsi 0x0000000000000000 $rdi 0x0000000000000000
$rbp 0x00007fffffffe0a8 $rsp 0x00007fffffffe098 $r8 0x0000000000000000
$r9 0x0000000000000000 $r10 0x0000000000000000 $r11 0x0000000000000000
$r12 0x0000000000000000 $r13 0x0000000000000000 $r14 0x0000000000000000
$r15 0x0000000000000000 $rip 0x000000000040113d $eflags 0x0000000000000202
this is callee
hello world
hello unix
** the target program terminated.
+31
View File
@@ -0,0 +1,31 @@
** program './deep' loaded. entry point 0x401131.
401131: f3 0f 1e fa endbr64
401135: 55 push rbp
401136: 48 89 e5 mov rbp, rsp
401139: 48 83 ec 10 sub rsp, 0x10
40113d: b8 00 00 00 00 mov eax, 0
** set a breakpoint at 0x40109c.
Num Address
0 0x40109c
** set a breakpoint at 0x401031.
Num Address
0 0x40109c
1 0x401031
** delete breakpoint 0.
Num Address
1 0x401031
** breakpoint 3 does not exist.
Num Address
1 0x401031
** hit a breakpoint at 0x401031.
401031: 48 89 c6 mov rsi, rax
401034: bf 01 00 00 00 mov edi, 1
401039: e8 20 01 00 00 call 0x40115e
40103e: 90 nop
40103f: c9 leave
Num Address
1 0x401031
this is callee
hello world
hello unix
** the target program terminated.
+44
View File
@@ -0,0 +1,44 @@
** program './game' loaded. entry point 0x401000.
401000: b9 05 00 00 00 mov ecx, 5
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
** set a breakpoint at 0x4010f1.
** enter a syscall(1) at 0x401052.
401052: 0f 05 syscall
401054: 59 pop rcx
401055: c3 ret
401056: 51 push rcx
401057: b8 01 00 00 00 mov eax, 1
guess a number :
** leave a syscall(1) = 18 at 0x401052.
401052: 0f 05 syscall
401054: 59 pop rcx
401055: c3 ret
401056: 51 push rcx
401057: b8 01 00 00 00 mov eax, 1
** enter a syscall(0) at 0x401088.
401088: 0f 05 syscall
40108a: 59 pop rcx
40108b: c3 ret
40108c: 51 push rcx
40108d: b8 00 00 00 00 mov eax, 0
** leave a syscall(0) = 2 at 0x401088.
401088: 0f 05 syscall
40108a: 59 pop rcx
40108b: c3 ret
40108c: 51 push rcx
40108d: b8 00 00 00 00 mov eax, 0
** hit a breakpoint at 0x4010f1.
4010f1: 48 8d 35 2b 0f 00 00 lea rsi, [rip + 0xf2b]
4010f8: ba 06 00 00 00 mov edx, 6
4010fd: 0f 05 syscall
4010ff: 59 pop rcx
401100: c3 ret
** enter a syscall(1) at 0x4010fd.
4010fd: 0f 05 syscall
4010ff: 59 pop rcx
401100: c3 ret
401101: b8 3c 00 00 00 mov eax, 0x3c
401106: 48 31 ff xor rdi, rdi
+44
View File
@@ -0,0 +1,44 @@
** program './game' loaded. entry point 0x401000.
401000: b9 05 00 00 00 mov ecx, 5
401005: 48 83 f9 00 cmp rcx, 0
401009: 74 1f je 0x40102a
40100b: e8 2b 00 00 00 call 0x40103b
401010: e8 5c 00 00 00 call 0x401071
** set a breakpoint at 0x4010f1.
** enter a syscall(1) at 0x401052.
401052: 0f 05 syscall
401054: 59 pop rcx
401055: c3 ret
401056: 51 push rcx
401057: b8 01 00 00 00 mov eax, 1
guess a number :
** leave a syscall(1) = 18 at 0x401052.
401052: 0f 05 syscall
401054: 59 pop rcx
401055: c3 ret
401056: 51 push rcx
401057: b8 01 00 00 00 mov eax, 1
** enter a syscall(0) at 0x401088.
401088: 0f 05 syscall
40108a: 59 pop rcx
40108b: c3 ret
40108c: 51 push rcx
40108d: b8 00 00 00 00 mov eax, 0
** leave a syscall(0) = 2 at 0x401088.
401088: 0f 05 syscall
40108a: 59 pop rcx
40108b: c3 ret
40108c: 51 push rcx
40108d: b8 00 00 00 00 mov eax, 0
** hit a breakpoint at 0x4010f1.
4010f1: 48 8d 35 2b 0f 00 00 lea rsi, [rip + 0xf2b]
4010f8: ba 06 00 00 00 mov edx, 6
4010fd: 0f 05 syscall
4010ff: 59 pop rcx
401100: c3 ret
** enter a syscall(1) at 0x4010fd.
4010fd: 0f 05 syscall
4010ff: 59 pop rcx
401100: c3 ret
401101: b8 3c 00 00 00 mov eax, 0x3c
401106: 48 31 ff xor rdi, rdi
+71
View File
@@ -0,0 +1,71 @@
from pwn import *
import time
import sys
import difflib
def read_file(filename):
"""Read a file and return its contents as a list of lines."""
with open(filename, "r") as f:
return f.readlines()
def normalize_line(line):
"""Normalize a line by stripping leading/trailing whitespace and reducing internal whitespace to a single space."""
return ' '.join(line.split())
def compare_files(file1, file2):
"""Compare two files and print the differences or 'accept' if they are the same."""
content1 = read_file(file1)
content2 = read_file(file2)
# Normalize lines to ignore whitespace differences
normalized1 = [normalize_line(line) for line in content1]
normalized2 = [normalize_line(line) for line in content2]
diff = difflib.unified_diff(normalized1, normalized2, fromfile=file1, tofile=file2)
# Convert the generator to a list to check if there are any differences
diff_list = list(diff)
if not diff_list:
print("accept")
else:
for line in diff_list:
print(line)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: ./run.py <test case id>")
sys.exit(1)
filename = "./in/" + sys.argv[1] + ".in"
f = open(filename)
input_lines = f.read().splitlines()
# start process
p_run = input_lines[0].split(" ")
if len(p_run) == 1:
p = process([p_run[0]])
else:
p = process([p_run[0]] + [p_run[1]])
for i in range(1, len(input_lines)):
# info(input_lines[i])
p.sendline(input_lines[i].encode())
time.sleep(0.2)
# wait
time.sleep(1)
# \x00, (sdb)...
with open("output.txt", "w", encoding="utf-8") as f:
output = p.recvall(timeout=1).decode("utf-8")
output = output.replace("\x00", "") # \x00 terminate
output = output.replace("(sdb) ", "")
output = output.replace("guess a number > ", "guess a number > \n")
f.write(output)
p.close()
ans_file = "./out/" + sys.argv[1] + ".ans"
info(ans_file)
compare_files("output.txt", ans_file)
+7
View File
@@ -0,0 +1,7 @@
** program 'test/hello' loaded. entry point 0x401000
 401000: f3 0f 1e fa endbr64
 401004: 55 push rbp
 401005: 48 89 e5 mov rbp, rsp
 401008: ba 0e 00 00 00 mov edx, 0xe
 40100d: 48 8d 05 ec 0f 00 00 lea rax, [rip + 0xfec]
(sdb) 
+27
View File
@@ -0,0 +1,27 @@
#include "vector.h"
#include <stdlib.h>
struct bps_node *bps = NULL;
int bps_len = 0, bps_cnt = 0, bps_max = 0;
const struct bps_node *find(uint64_t addr)
{
for (int i = 0; i < bps_len; i++)
if (bps[i].addr && bps[i].addr == addr)
return &bps[i];
return NULL;
}
int bps_push(uint64_t addr, uint8_t data)
{
if (bps_max == 0)
bps = malloc((bps_max = 1) * sizeof(struct bps_node));
if (bps_len + 1 >= bps_max)
bps = realloc(bps, (bps_max <<= 1) * sizeof(struct bps_node));
bps[bps_len].addr = addr;
bps[bps_len].data = data;
bps_cnt++;
return bps_len++;
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
struct bps_node {
uint64_t addr;
uint8_t data;
};
const struct bps_node *find(uint64_t addr);
int bps_push(uint64_t addr, uint8_t data);
extern struct bps_node *bps;
extern int bps_len, bps_cnt, bps_max;