[C++] 纯文本查看 复制代码
#include "unicorn/unicorn.h"
#include <cstdint>
#include <cstdio>
uint8_t code[] = "\x93\xc0\x50\x04\x93\xc0\x90\x08\x93\xc0\x20\x00\x83\x01\x01\x00\x93\xf1\xf1\x0f\x93\xc1\x41\x07\xb3\x80\x30\x40";
uint8_t target[] = "\x44\x4e\x57\xc0\x85\x57\x51\x48\xb6\xa4\x5a\x5b\x5c\xd3\x84\x6c\x46\x7a\xd8\x8f\x6c\x5d\x6c\xd5\x98\x5c\x49";
// xori x1, x1, 0x45 0
// xori x1, x1, 0x89 4
// xori x1, x1, 0x2 8
// lb x3, 0(x2) c
// andi x3, x3, 0xff 10
// xori x3, x3, 0x74 14
// sub x1, x1, x3 18
#define OK(x) do { uc_err err = x; if (err) { std::abort(); }} while(0)
void hook_addr(uc_engine* uc, uint64_t addr, size_t sz, void* data) {
uint64_t combined = *((uint64_t*)data);
uint32_t val, pc;
uint64_t input = combined & (0xFFFFFFFF);
uint64_t round = (combined & (0xFFFFFFFF00000000UL) ) >> 32;
uint32_t x2 = round + 0x8000;
OK(uc_reg_write(uc, UC_RISCV_REG_X2, &x2));
if (addr == 0x7000 + 4) {
if ( round % 5 >= 4) {
val = input ^ 158;
pc = addr + 2 * 4;
//printf("input=%hx val!\n", input);
OK(uc_reg_write(uc, UC_RISCV_REG_X1, &val));
OK(uc_reg_write(uc, UC_RISCV_REG_PC, &pc));
} else if (round % 5 <= 2) {
val = addr + 4;
//printf("input=%hx redo!\n", input);
OK(uc_reg_write(uc, UC_RISCV_REG_PC, &val));
}
} else if (addr == 0x7000 + 8) {
if (round % 5 == 1 || round % 5 == 3) {
OK(uc_reg_read(uc, UC_RISCV_REG_X1, &val));
//printf("input=%hx x1=%hx mod!\n", input, val);
val = (val + 7) % 256;
OK(uc_reg_write(uc, UC_RISCV_REG_X1, &val));
}
}
}
int main() {
uc_engine* uc;
uc_hook hk;
uint32_t x1;
uint64_t input;
OK(uc_open(UC_ARCH_RISCV, UC_MODE_32, &uc));
OK(uc_mem_map(uc, 0x6000, 0x3000, UC_PROT_ALL));
OK(uc_mem_write(uc, 0x7000, code, sizeof(code)));
OK(uc_mem_write(uc, 0x8000, target, sizeof(target)));
OK(uc_hook_add(uc, &hk, UC_HOOK_CODE, (void*)hook_addr, (void*)&input, 1, 0));
for (uint64_t i = 0; i < 27 + 1; i ++) {
input = getchar();
if (i == 27) {
if (input != (uint64_t)'\n') {
printf("Try harder!\n");
std::exit(0);
} else{
break;
}
}
input |= (i << 32);
x1 = input;
OK(uc_reg_write(uc, UC_RISCV_REG_X1, &x1));
x1 = 0;
OK(uc_reg_write(uc, UC_RISCV_REG_X2, &x1));
OK(uc_reg_write(uc, UC_RISCV_REG_X3, &x1));
OK(uc_emu_start(uc, 0x7000, 0x7000 + sizeof(code) - 1, 0, 0));
OK(uc_reg_read(uc, UC_RISCV_REG_X1, &x1));
if (x1 != 0) {
printf("Try harder!\n");
std::exit(0);
}
}
printf("You are the real pro!\n");
OK(uc_close(uc));
}