wtdcode 发表于 2021-12-6 07:02

新人第一次尝试CM,欢迎尝试

本帖最后由 wtdcode 于 2021-12-6 07:54 编辑

正确的话会输出 You are the real pro!

错误的话会输出 Try harder!

没有壳,没有花指令,不要被反汇编吓到了,提示:Unicorn Engine



预期解包括逆向算法和爆破,两种做法都很有意思,可以都尝试一下。期待有人能给出算法 {:1_905:}

搜索曾经的回忆 发表于 2021-12-7 15:18

__int64 sub_401783()
{
__int64 input; // BYREF
int INPUT; // BYREF
char v3; // BYREF
__int64 uc; // BYREF
unsigned __int64 i; //

sub_142DED0();
if ( uc_open(8i64, 4i64, &uc) )
    abort();
if ( uc_mem_map(uc, 0x6000i64, 0x3000i64, 7i64) )
    abort();
if ( uc_mem_write(uc, 0x7000i64, &unk_1437010, 29i64) )
    abort();
if ( uc_mem_write(uc, 0x8000i64, &unk_1437030, 28i64) )
    abort();
if ( uc_setHook(uc, v3, 4i64, sub_401550, &input, 1i64, 0i64) )
    abort();
for ( i = 0i64; i <= 0x1B; ++i )
{
    input = getchar();
    if ( i == 27 )
    {
      if ( input != 10 )
      {
      put("Try harder!\n");
      exit(0);
      }
      break;
    }
    input |= i << 32;
    INPUT = input;
    if ( uc_reg_write(uc, 2, &INPUT) )          // al=input
                                                //
      abort();
    INPUT = 0;
    if ( uc_reg_write(uc, 3, &INPUT) )
      abort();
    if ( uc_reg_write(uc, 4, &INPUT) )
      abort();
    if ( uc_start(uc, 0x7000i64, 0x701Ci64, 0i64, 0i64) )
      abort();
    if ( uc_reg_read(uc, 2i64, &INPUT) )      // 获取al
      abort();
    if ( INPUT )
    {
      put("Try harder!\n");
      exit(0);
    }
}
put("You are the real pro!\n");
if ( uc_close(uc) )
    abort();
return 0i64;
}
unsigned __int64 __fastcall sub_401550(__int64 a1, __int64 a2, __int64 a3, __int64 *a4)
{
unsigned __int64 result; // rax
int v5; // eax
int v6; // BYREF
int v7; // BYREF
int v8; // BYREF
int v10; //
int v11; //
int v13; //
unsigned __int64 v14; //
__int64 v15; //
unsigned __int64 v16; //

v16 = *a4;
v15 = v16;
v14 = HIDWORD(v16);
v6 = HIDWORD(v16) + 0x8000;
result = uc_reg_write(a1, 3, &v6);
v13 = result;
if ( result )
    abort();
if ( a2 == 0x7004 )
{
    if ( v14 % 5 <= 3 )
    {
      result = v14 % 5;
      if ( v14 % 5 <= 2 )
      {
      v8 = 28680;
      result = uc_reg_write(a1, 190, v8);
      v10 = result;
      if ( result )
          abort();
      }
    }
    else
    {
      v5 = v15;
      LOBYTE(v5) = v15 ^ 0x9E;
      v8 = v5;
      v7 = 28684;
      if ( uc_reg_write(a1, 2, v8) )
      abort();
      result = uc_reg_write(a1, 190, &v7);
      v8 = result;
      if ( result )
      abort();
    }
}
else if ( a2 == 0x7008 )
{
    if ( v14 % 5 == 1 || (result = v14 % 5, v14 % 5 == 3) )
    {
      if ( uc_reg_read(a1, 2i64, v8) )
      abort();
      v8 = (LOBYTE(v8) + 7);
      result = uc_reg_write(a1, 2, v8);
      v11 = result;
      if ( result )
      abort();
    }
}
return result;
}
没时间搞了,给后来者一点提示吧,该标注的都标注了

wtdcode 发表于 2021-12-8 19:42

考虑已经有人解出来了,所以直接公布代码

#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, 0x28
// 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));
}

weikun444 发表于 2021-12-6 17:57

本帖最后由 weikun444 于 2021-12-7 06:56 编辑

无奈,不懂算法,感兴趣的可以跟跟1783

wtdcode 发表于 2021-12-6 18:30

weikun444 发表于 2021-12-6 17:57
无奈,不懂算法,爆的话,1783下断,18A3改NOP,18AD改JMP即可!

我说的爆破指的是通过枚举的方法得到正确的key{:1_918:}

不过在现实的攻防里这也是一种办法哈哈

Ichild 发表于 2021-12-7 15:29

#include <stdio.h>
#include <string.h>

unsigned char data[] = {68, 78, 87, 192, 133, 87, 81, 72, 182, 164, 90, 91, 92, 211, 132, 108, 70, 122, 216, 143, 108, 93, 108, 213, 152, 92, 73, 0};

/*
00007000        xori        ar, ar, 0x45
00007004        xori        ar, ar, 0x89
00007008        xori        ar, ar, 0x2
0000700c        lb                gp, 0x0 =>Stack (sp)
00007010        andi        gp, gp, 0xff
00007014        xori        gp, gp, 0x74
00007018        sub                ar, ar, gp
/**/
unsigned int check_elem(char value_in, int index) {
        unsigned char value = value_in;

label_7004:
        if (index % 5 == 4) {
                value ^= 0x9E;
                goto label_700C;
        } else {
                value ^= 0x45;
                if (index % 5 != 3) goto label_7008;
        }
        value ^= 0x89;

label_7008:
        if (index % 5 == 1 || index % 5 == 3) {
                value += 7;
        }
        value ^= 0x2;

label_700C:
        return value - (data ^ 0x74);
}

void reverse() {
        char input;
        input = 0;
        for (int i = 0; i < 27; i++) {
                unsigned char value = data ^ 0x74;
                if (i % 5 == 4) {
                        value ^= 0x9E;
                } else {
                        value ^= 0x2;
                        if (i % 5 == 1 || i % 5 == 3) {
                                value -= 7;
                        }
                        if (i % 5 == 3) value ^= 0x89;
                        value ^= 0x45;
                }
                input = value;
        }
        puts(input);
}

int check(char* input) {
        if (strlen(input) != 27 && (strlen(input) != 28 || input != '\n')) return 0;
        for (int i = 0; i < 27; i++) {
                if (check_elem(input, i) != 0) return 0;
        }
        return 1;
}

int main() {
        /*
        if (check("wtdcode{uNicoRn_lIke_a_Pro}")) {
                puts("OK.");
        } else {
                puts("NOP.");
        }
        /**/
        reverse();
        return 0;
}

wtdcode 发表于 2021-12-7 16:40

Ichild 发表于 2021-12-7 15:29
#include
#include



正解 非常干净漂亮。

wtdcode 发表于 2021-12-7 16:41

搜索曾经的回忆 发表于 2021-12-7 15:18
__int64 sub_401783()
{
__int64 input; // BYREF


{:1_918:}很接近了

搜索曾经的回忆 发表于 2021-12-7 18:47

wtdcode 发表于 2021-12-7 16:41
很接近了

模拟的是x86的汇编指令集吗?还是?

wtdcode 发表于 2021-12-7 18:49

搜索曾经的回忆 发表于 2021-12-7 18:47
模拟的是x86的汇编指令集吗?还是?

RISC-V 上面正解里已经给出反汇编了

搜索曾经的回忆 发表于 2021-12-7 18:55

wtdcode 发表于 2021-12-7 18:49
RISC-V 上面正解里已经给出反汇编了

额,查unicorn官方文档,没查到这个指令集
页: [1] 2
查看完整版本: 新人第一次尝试CM,欢迎尝试