吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2457|回复: 16
收起左侧

[ReverseMe] 新人第一次尝试CM,欢迎尝试

[复制链接]
wtdcode 发表于 2021-12-6 07:02
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

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

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

错误的话会输出 Try harder!

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



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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 1热心值 +1 收起 理由
ICAC陆志廉 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

搜索曾经的回忆 发表于 2021-12-7 15:18
[C] 纯文本查看 复制代码
__int64 sub_401783()
{
  __int64 input; // [rsp+48h] [rbp-58h] BYREF
  int INPUT; // [rsp+54h] [rbp-4Ch] BYREF
  char v3[8]; // [rsp+58h] [rbp-48h] BYREF
  __int64 uc; // [rsp+60h] [rbp-40h] BYREF
  unsigned __int64 i; // [rsp+98h] [rbp-8h]

  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;
}

[C] 纯文本查看 复制代码
unsigned __int64 __fastcall sub_401550(__int64 a1, __int64 a2, __int64 a3, __int64 *a4)
{
  unsigned __int64 result; // rax
  int v5; // eax
  int v6; // [rsp+24h] [rbp-3Ch] BYREF
  int v7; // [rsp+28h] [rbp-38h] BYREF
  int v8[2]; // [rsp+2Ch] [rbp-34h] BYREF
  int v10; // [rsp+38h] [rbp-28h]
  int v11; // [rsp+3Ch] [rbp-24h]
  int v13; // [rsp+44h] [rbp-1Ch]
  unsigned __int64 v14; // [rsp+48h] [rbp-18h]
  __int64 v15; // [rsp+50h] [rbp-10h]
  unsigned __int64 v16; // [rsp+58h] [rbp-8h]

  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[0] = 28680;
        result = uc_reg_write(a1, 190, v8);
        v10 = result;
        if ( result )
          abort();
      }
    }
    else
    {
      v5 = v15;
      LOBYTE(v5) = v15 ^ 0x9E;
      v8[0] = v5;
      v7 = 28684;
      if ( uc_reg_write(a1, 2, v8) )
        abort();
      result = uc_reg_write(a1, 190, &v7);
      v8[1] = 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[0] = (LOBYTE(v8[0]) + 7);
      result = uc_reg_write(a1, 2, v8);
      v11 = result;
      if ( result )
        abort();
    }
  }
  return result;
}

没时间搞了,给后来者一点提示吧,该标注的都标注了
 楼主| wtdcode 发表于 2021-12-8 19:42
考虑已经有人解出来了,所以直接公布代码

[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));
}
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

不过在现实的攻防里这也是一种办法哈哈
Ichild 发表于 2021-12-7 15:29
[C] 纯文本查看 复制代码
#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 [0x0](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[index] ^ 0x74);
}

void reverse() {
	char input[28];
	input[27] = 0;
	for (int i = 0; i < 27; i++) {
		unsigned char value = data[i] ^ 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[i] = value;
	}
	puts(input);
}

int check(char* input) {
	if (strlen(input) != 27 && (strlen(input) != 28 || input[27] != '\n')) return 0;
	for (int i = 0; i < 27; i++) {
		if (check_elem(input[i], 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
[mw_shl_code=c,true]#include
#include

正解 非常干净漂亮。
 楼主| wtdcode 发表于 2021-12-7 16:41
搜索曾经的回忆 发表于 2021-12-7 15:18
[mw_shl_code=c,true]__int64 sub_401783()
{
  __int64 input; // [rsp+48h] [rbp-58h] BYREF

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

模拟的是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官方文档,没查到这个指令集
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 05:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表