吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 23726|回复: 66
收起左侧

[原创] 【160 crackme 之52 】 注册码算法分析

  [复制链接]
6767 发表于 2017-8-22 07:22
本帖最后由 6767 于 2017-12-24 21:18 编辑

160CM 里面的三个5星难度之一

052.esgis.1

UPX 0.89 - 3.xx -> Markus & Laszlo ver. [ 0.76 ] <- from file.
A classic viusal C++ programe, compiled at 1998.

Headers

长文预警
本文大概有三千个字

先上图;

SuccessfulCracked
SuccessfulCracked.png

使用linxue的脱壳机去掉packer,或者使用通用oep大法,upx主要是压缩没有加密,反正也不难。
追踪 引用字符串找到函数结点;

int __thiscall sub_401C20(void *this) {
    void *_this; // ebp@1
    unsigned int len_plus1; // kr20_4@1
    char *v3; // edi@1
    int v4; // eax@1
    int Ntimes64; // esi@3
    int ii; // edi@3
    int result; // eax@6
    signed int j; // esi@7
    unsigned int *guessPtr; // edi@7
    signed int i; // eax@9
    DWORD Type; // [sp+10h] [bp-608h]@1
    DWORD cbData; // [sp+14h] [bp-604h]@1
    HKEY phkResult; // [sp+18h] [bp-600h]@1
    int guessHex; // [sp+1Ch] [bp-5FCh]@5
    char v15; // [sp+20h] [bp-5F8h]@5
    char v16; // [sp+24h] [bp-5F4h]@5
    char v17; // [sp+28h] [bp-5F0h]@5
    int C0_FF_0[2]; // [sp+2Ch] [bp-5ECh]@1
    int v19; // [sp+34h] [bp-5E4h]@3
    char userString[500]; // [sp+3Ch] [bp-5DCh]@1
    BYTE tmp; // [sp+230h] [bp-3E8h]@1
    CHAR guessString; // [sp+424h] [bp-1F4h]@1

    _this = this;
    memset(userString, 0, sizeof(userString));
    memset(&guessString, 0, 0x1F4u);
    memset(&tmp, 0, 0x1F4u);
    getStrFromTextBox(this + 92, userString, 100);
    getStrFromTextBox(_this + 172, &guessString, 100);
    strcpy(&tmp, userString);
    _strrev(&tmp);                                // input1 reversed
    strcat(userString, &tmp);                     // normal+reversed str
    RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", &phkResult);
    Type = 1;
    cbData = 256;
    RegQueryValueExA(phkResult, "ProductID", 0, &Type, &tmp, &cbData);
    Type = 1;
    strcat(userString, &tmp);
    cbData = 256;
    RegQueryValueExA(phkResult, "RegisteredOwner", 0, &Type, &tmp, &cbData);
    strcat(userString, &tmp);                     // 1234_4321_4321_4321
    len_plus1 = strlen(userString) + 1;
    setConst_4016E0(C0_FF_0);
    memset(&userString[len_plus1 - 1], 0, 76u);
    v3 = &userString[len_plus1 + 75];
    *v3 = 0;
    v3[2] = 0;
    v4 = 64 - (len_plus1 & 0x3F);
    userString[len_plus1 - 1] = 0x80u;
    if ( v4 <= 7 )
        v4 += 64;
    Ntimes64 = v4 + len_plus1;
    ii = 0;
    for ( *(&v19 + v4 + len_plus1) = 8 * strlen(userString); ii < Ntimes64; ii += 64 )
        MD5like_401700(&userString[ii], C0_FF_0);       // MD5 like
    //
    C0_FF_0[0] = LOWORD(C0_FF_0[0]);
    if ( sscanf(&guessString, "%lx%lx%lx%lx", &guessHex, &v15, &v16, &v17) == 4 ) { // guess text like :'0x12341234 0x12341234 0x12341234 0x12341234'
        j = 0;
        guessPtr = &guessHex;
        do {
            rolN_401B90(guessPtr, 0xBADC0DE / (j++ + 0x50));
            ++guessPtr;
        } while ( j < 3 );
        i = 0;
        while ( *(&guessHex + i * 4) == C0_FF_0 ) {
            ++i;
            if ( i >= 4 )
                return msgbox_4100A8("... Man, you're good enough to join CORE! ...", "Welcome", 0x40u);
        }
        result = msgbox_4100A8("... Better luck next time ...", "Failed", 0x30u);
    } else {
        result = msgbox_4100A8("... Hmmm, you don't even pass the first threshold ...", "Failed", 0x30u);
    }
    return result;
}

主要函数就在这个block里。
内存地址:0x19ed24
inputtext1.会操作3次得到一个4倍长度的strings1(Win10注册表是空,直接复制3次),inputtext2以%lx的方式读入4个,然后调用sub_401B90循环移位N次得到一个16bytes的字符串,与strings1 的类似MD5摘要结果进行比较。

input1->(like MD5 digest)——┐
                          cmp---(Y/N)
input2->(ROL+strange+1)___」

MD5 like func

使用PEid的Krypto 插件检查算法会发现有且仅有md5算法,
地址块 :dword_41B0B0;

所有的常数(F G H I)里面的都是对的,包括UPX0:setConst_4016E0函数 sets initial magic number;
但是,怎么看这个函数都不是正常的标准md5,也没有动力去分析一个修改过的md5;
考虑到在UPX0:00401E56还and了一个0xffff,表明直接爆破md5是不可能的了;
不过可以在内存地址里得到摘要值;

对应于 "0000"的输入,摘要值是

0019ED34  |BB A2 00 00 B8 2E 9A A3  |  42 25 88 E8 70 B8 C4 9D|  ........B%..p...

这16bytes数据;

ROL strange array

这个函数是最有意思的函数;开始的时候发现它每次循环修改2 int,
c[0,1],c[1,2],c[2,3],
循环3次刚刚好全部的16bytes

查看反汇编伪代码

char *__cdecl rolN_401B90(unsigned int *ptr, int const1)
{
  char *result; // eax@1
  int cnt; // ebx@1
  unsigned int Lsi; // esi@1
  unsigned int Hdi; // edi@1
  unsigned __int64 tt0; // rax@2
  int t1; // esi@2
  int t2; // edi@2
  unsigned __int64 tt; // rax@2

  result = ptr;
  cnt = const1;
  Lsi = *ptr;
  Hdi = ptr[1];
  if ( const1 )
  {
    do
    {
      tt0 = 2 * __PAIR__(Hdi, Lsi);
      LODWORD(tt0) = ((2 * Lsi) | (Hdi >> 31)) & 4;
      t1 = tt0 | (Hdi >> 31);
      t2 = HIDWORD(tt0);
      tt = tt0 << 11;
      LODWORD(tt) = t1 & 0x2000 ^ tt;
      tt <<= 18;
      LODWORD(tt) = t1 & 0x80000000 ^ tt;
      tt *= 2i64;
      Lsi = tt ^ t1;
      Hdi = HIDWORD(tt) ^ t2;
      --cnt;//IDA监控点
    }
    while ( cnt );
    result = ptr;
  }
  *result = Lsi;
  *(result + 1) = Hdi;
  return result;
}

不好意思,研究了好久发现,这个代码是错误的,但是只有试过才大概了解到一大堆位运算在干嘛;
在这个地方卡了好久,花时间修改导出的C代码,发现是错误的计算结果;

经过汇编跟踪比较,发现伪代码错误,放弃;

用IDA dump脚本监控前几百次运行是这样的:

   ebx,         esi,     edi,  
0,00255F35,00000001,00000002,0000000200000001
1,00255F35,00000002,00000004,0000000400000002
2,00255F34,00000004,00000009,0000000900000004*
3,00255F33,00000008,00000012,0000001200000008
4,00255F32,00000010,00000024,0000002400000010
5,00255F31,00000020,00000048,0000004800000020
6,00255F30,00000040,00000090,0000009000000040
7,00255F2F,00000080,00000120,0000012000000080
8,00255F2E,00000100,00000240,0000024000000100
9,00255F2D,00000200,00000480,0000048000000200
A,00255F2C,00000400,00000900,0000090000000400
B,00255F2B,00000800,00001200,0000120000000800
C,00255F2A,00001000,00002400,0000240000001000
D,00255F29,00002000,00004801,0000480100002000*
E,00255F28,00004000,00009002,0000900200004000

Try Brute force

这里走歪了;

这个函数 接受 4 uint,运行后和md5like 的摘要比较,得到是否正确;
前面说到了,直接用导出的fake C code是不能用的,于是我们想要爆破的话,直接用汇编代码来运行就好了嘛;

这里主要写内联汇编,把rolN_401B90 函数的汇编代码提取出来,在vs2015里改写接口部分,

__declspec(naked)
char* __cdecl rolN_401B90(unsigned int *Cptr, int Cconst1) {

        //checked match original funcs
#define ptr 4
#define const1 8

        __asm {
                mov     eax, [esp + ptr]
                        push    ebx
                        mov     ebx, [esp + 4 + const1]
                        push    esi
                        mov     esi, [eax]
                        push    edi
            ...MORE...
            RETZERO:; CODE XREF : __allshl + 3j
                        xor     eax, eax
                        xor     edx, edx
                        retn
        }
#undef ptr 
#undef const1
}

运行了一个测试,发现是正确的;
于是写了一个爆破Generator function 来初始化输入值,每10000次打个log;
结果是,原始汇编代码运行1W次时间,4~5minutes,

如果要爆破完16bytes,需要集群了,emm.....
有没有土豪赞助我一车GTX1080和i7 7700K 吗

直接爆破不行,就需要分析这个汇编blocks在干嘛,这里现在看来是最最重要的

前面调试可以看到全部是位运行,既然是数学,这里使用符号传递来尝试分析;事实证明这个方法是正确的。

 ; char* __declspec(naked) __cdecl rolN_401B90(unsigned int *ptr, int const1)
 rolN_401B90     proc near               ; CODE XREF: sub_401C20+284p
 ;ptr             = dword ptr  4
 ;const1          = dword ptr  8
                 mov     eax, [esp+ptr]
                 push    ebx
                 mov     ebx, [esp+4+const1];cnt;

                 push    esi
                 mov     esi, [eax];c[0]
                 push    edi
                 mov     edi, [eax+4];c[1]

                 test    ebx, ebx
                 jbe     short loc_401C15
                 push    ebp

 loop1:                             ; CODE XREF: rolN_401B90+7Ej
                 mov     ebp, edi
                 mov     ecx, 1     ;ecx=1;
                 shr     ebp, 1Fh
                 mov     [esp+10h+const1], ebp;get c[1].bit31;
                 mov     eax, esi
                 mov     edx, edi
                 xor     ebp, ebp       ;ebp=0
                 call    __allshl;            edx,eax <<1
                 ;eax=c[0]<<1
                 ;edx=c[1]<<1|c[0]>>31;
                 mov     ecx, [esp+10h+const1];ecx=c[1]>>31
                 or      ebp, edx       ; mov ebp,edx;
                                        ;ebp=c[1]<<1 | c[0]>>31;
                 or      ecx, eax       ;ecx=c[1]>>31|(c[0]<<1);
                 xor     edx, edx       ;edx=0;
                 mov     esi, ecx       ;esi=c[1]>>31|(c[0]<<1);
                 mov     ecx, 11        ;ecx=11
                 mov     eax, esi       ;eax=c[1]>>31|(c[0]<<1);
                 mov     edi, ebp       ;edi=c[1]<<1 | c[0]>>31 ;
                 and     eax, 4         ;eax=(c[1]>>31|(c[0]<<1)) & 4;
                 call    __allshl
                 ;eax=((c[1].bit31|(c[0]<<1)) & 4)<<11
                 ;eax=((c[1]>>31  |(c[0]<<1)) & 4)<<11
                 ;eax=((c[0]<<1) & 4)<<11
                 ;eax=( c[0]&2 ) <<12
                 ;edx=0
                 mov     ecx, esi       ;ecx=c[1]>>31|(c[0]<<1)
                 xor     ebp, ebp       ;ebp=0
                 and     ecx, 2000h     ;ecx=(c[1]>>31|(c[0]<<1)) & 0x2000
                                        ;ecx=(c[0]<<1) & 0x2000 
                 xor     edx, ebp       ;NOP  ;ebp==0
                 xor     eax, ecx       ;eax=(((c[0]<<1) & 4)<<11) ^ (c[0]<<1 & 0x2000)
                                        ;eax=(    ( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000)
                 mov     ecx, 12h       ;ecx=18;
                 call    __allshl
                 ;eax=( (( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000)) <<  18 
                 ;edx=( (( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000)) >>  14   Always edx==0
                 ;
                 mov     ecx, esi       ;ecx=c[1]>>31|(c[0]<<1);
                 xor     edx, ebp       ;NOP,ebp==0;
                 and     ecx, 80000000h ;ecx=c[1].bit31|(c[0]<<1) & 0x8000_0000;
                                        ;ecx=(c[0]<<1) & 0x8000_0000;
                 xor     eax, ecx       
                 ;eax=(  ((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000))<<18 )^( (c[0]<<1) & 0x8000_0000 )
                 mov     ecx, 1         ;ecx=1
                 call    __allshl
                 ;eax=((  ((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000))<<18 )^( (c[0]<<1) & 0x8000_0000 ))<<1;
                 ;edx=(  ((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000)) >> 14)<<1 |( (((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000))<<18 )^( (c[0]<<1) & 0x8000_0000 ) )>>31

                 xor     esi, eax
                ;c[0]=(c[1]>>31|(c[0]<<1))   ^(   ((((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000))<<18 )^( (c[0]<<1) & 0x8000_0000 ))<<1  )
                ;                           ^ ((c[0].bit1<<31 ^ c[0].bit12<<31 ^ c[0].bit30<<31 )<<1)
                ;c[0]=(c[1]>>31|(c[0]<<1)) ^ 0
                ;c[0]= c[1]>>31|(c[0]<<1)

                 xor     edi, edx
                ;c[1]=(c[1]<<1 | c[0]>>31)   ^( (  ((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000)) >> 14)<<1 |( (((( c[0]&2 ) <<12) ^ (c[0]<<1 & 0x2000))<<18 )^( (c[0]<<1) & 0x8000_0000 ) )>>31 )
                ;                               (        c[0].bit1<<13^  c[0].bit12<<13    )>>14  <<1
                ;c[1]=(c[1]<<1 | c[0]>>31)   ^(        0                                              |(c[0].bit1<<31 ^ c[0].bit12<<31 ^ c[0].bit30<<31 )>>31)
                ;c[1]=(c[1]<<1 | c[0]>>31)   ^(c[0].bit1 ^ c[0].bit12 ^ c[0].bit30 )
                ;c[1]=(c[1]<<1 | c[0]>>31)   ^(c[0]>>1 ^c[0]>>12 ^c[0]>>30)&1
                ;c[1]= c[1]<<1 ^ (c[0]>>31 ^c[0]>>1 ^c[0]>>12 ^c[0]>>30)&1
                 dec     ebx
                 jnz     short loop1
                 mov     eax, [esp+10h+ptr]
                 pop     ebp

 loc_401C15:                             ; CODE XREF: rolN_401B90+12j
                 mov     [eax], esi
                 mov     [eax+4], edi
                 pop     edi
                 pop     esi
                 pop     ebx
                 retn
                endp

 __allshl        proc near               ; CODE XREF: rolN_401B90+29p
                                         ; rolN_401B90+46p ...
                ; cmp     cl, 40h
                ; jnb     short RETZERO
                ; cmp     cl, 20h
                ; jnb     short MORE32
                 shld    edx, eax, cl
                 shl     eax, cl
                 retn
 ; ---------------------------------------------------------------------------
 MORE32:                                 ; CODE XREF: __allshl+8j
                 mov     edx, eax
                 xor     eax, eax
                 and     cl, 1Fh
                 shl     edx, cl
                 retn
 ; ---------------------------------------------------------------------------
 RETZERO:                                ; CODE XREF: __allshl+3j
                 xor     eax, eax
                 xor     edx, edx
                 retn
                endp

简单来说,
被操作的2个uint 会循环N次,
每次操作

c[1]=(c[1]<<1 | c[0]>>31)   ^(c[0]>>1 ^c[0]>>12 ^c[0]>>30)&1
c[0]= c[1]>>31|(c[0]<<1)

差不多就是两个uint32 相互循环移位,附加c[1]一个特殊的最低位XOR,条件是c[0]的c[0].bit1 ^ c[0].bit12 ^ c[0].bit30 的异或 ;

得到这个算法以后写了个C代码测试,验证正确,结果又尝试了爆破,嗯,在编译器O2优化下 2mins/1W 计数;
不行,这个速度太慢了,于是按照逻辑写了个纯汇编的函数,手写的主要循环体优化后只有9行汇编代码,运行速度1mins/1W 计数,还是不够快

柳暗花明又一村

算法已知是迭代的,普通不能爆破,那就只能找算法的特性/漏洞了,比如通项函数什么的。
但是,上面的C表述基本不能看出什么;
于是就画了好几个算法运行的示意图

最后就这个看出端倪了。
draft1
draft1.jpg
可以回代运算(N+1)项得到第N项;

核心是 c[0]的n项的0~30bit在c[0]的n+1项的1~31bit, c[0]n项缺少的 31bit可以从c[0]的n+1项的31,13,2和c[1]的n+1项的最低位这四个东西异或得到;

C代码表述

char* rolN_reverse(uint32_t* ptr, int cnt) {
        uint32_t n[2], n_1[2];
        n[0] = ptr[0];
        n[1] = ptr[1];
        printf("[-]Get: %X %X\n", n[0], n[1]);
        for (int i = 0; i < cnt; i++) {
                n_1[0] = (n[0] >> 1 & 0x7fffffff)|((n[1]&1 ^ n[0]>>31^ n[0]>>13^ n[0]>>2)&1)<<31;

                n_1[1] = (n[1] >> 1 &0x7fffffff )|n[0]<<31;
                n[0] = n_1[0];
                n[1] = n_1[1];
        }
        printf("[-]Rev: %X %X\n", n[0], n[1]);
        ptr[0] = n[0];
        ptr[1] = n[1];
        return ptr;
}

写了个函数验证,结果正确;

不考虑奇怪的MD5,

最后把注册机(的½)写一下就是

#define V0 0xA2BB
#define V1 0XA39A2EB8
#define V2 0XE8882542
#define V3 0X9DC4B870

#define CV0 0x255f35
#define CV1 0x24e918
#define CV2 0x2475dd

uint32_t knownArray[4] = {V0,V1,V2,V3};
        rolN_reverse(knownArray + 2, CV2 );
        rolN_reverse(knownArray + 1, CV1);
        rolN_reverse(knownArray + 0, CV0);
        for (int i = 0; i < 4; i++) {
                printf(" 0x%X", knownArray);
        }
/*
[-]Get: E8882542 9DC4B870
[-]Rev: D4787858 54130406
[-]Get: A39A2EB8 D4787858
[-]Rev: 8C0D43AF 50B025BA
[-]Get: A2BB 8C0D43AF
[-]Rev: 2C6B2A6D EF4CABB9
 input:0000
 input:0x2C6B2A6D 0xEF4CABB9 0x50B025BA 0x54130406
*/    

所以,

SuccessfulCracked

成功完成任务;

期间各种奇奇怪怪的bug和错误歧途就不再描述了。。。

Summary

  • 内联汇编,x86 asm
  • Z3符号引擎 不知道能不能用上帮助分析,手动分析汇编逻辑还是太慢了;
  • 不要一条路走到黑,比如爆破什么的。~( ̄▽ ̄)~*
  • 笔和草稿纸需常备案头,in case of something;
  • ...

欢迎大家点评/闲聊

防止乱码 egis.1.Solved.7z (593.97 KB, 下载次数: 29) 在这里

撸了一个注册机, KeyGen.zip (72.78 KB, 下载次数: 44)


这个CM.052终于完整了

点评

吼啊吼啊!  发表于 2017-8-30 14:12

免费评分

参与人数 25吾爱币 +29 热心值 +25 收起 理由
pk8900 + 1 + 1 这个已经被我彻底征服了,用了三天时间,可以参照我的帖子。
lapop + 1 + 1 我很赞同!
webmarksman + 1 + 1 谢谢@Thanks!
小_Ta + 1 + 1 谢谢@Thanks!
MaxMadcc + 1 + 1 谢谢@Thanks!
白童话 + 1 + 1 热心回复!
dryzh + 1 + 1 用心讨论,共获提升!
hackeydg + 1 + 1 热心回复!
KaQqi + 1 我很赞同!
简直舒 + 1 + 1 我很赞同!
lies2014 + 1 + 1 用心讨论,共获提升!
小俊 + 1 + 1 热心回复!
whyida + 2 + 1 热心回复!
alienhh + 1 + 1 热心回复!
paopao1637 + 1 + 1 谢谢@Thanks!
610100 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
C0d3r1iu + 1 + 1 我很赞同!
2864095098 + 1 + 1 热心回复!
helloword121 + 1 + 1 谢谢@Thanks!
SomnusXZY + 1 + 1 热心回复!
NO_25 + 1 + 1 用心讨论,共获提升!
kissyou + 1 + 1 谢谢@Thanks!
平淡最真 + 3 + 1 用心讨论,共获提升!
Three_fish + 1 + 1 谢谢@Thanks!
zbnysjwsnd8 + 2 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

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

whyida 发表于 2017-9-5 11:54
楼主是否可以贴暴力测试的代码。我测试没通过,感觉是指针问题。谢谢
[C] 纯文本查看 复制代码
#include <stdio.h>

#define V0 0x12345
#define V1 0X23456
#define V2 0X41A4309F
#define V3 0X6F6A7DCB

#define CV0 0x255f35
#define CV1 0x24e918
#define CV2 0x2475dd
typedef unsigned __int32 uint32_t;
 int * rolN_reverse( int *Cptr,int Cconst1)
{	
/*
        uint32_t n[2], n_1[2];
        n[0] = ptr[0];
        n[1] = ptr[1];
        printf("[-]Get: %X %X\n", n[0], n[1]);
        for (int i = 0; i < cnt; i++) {
                n_1[0] = (n[0] >> 1 & 0x7fffffff)|((n[1]&1 ^ n[0]>>31^ n[0]>>13^ n[0]>>2)&1)<<31;

                n_1[1] = (n[1] >> 1 &0x7fffffff )|n[0]<<31;
                n[0] = n_1[0];
                n[1] = n_1[1];
        }
        printf("[-]Rev: %X %X\n", n[0], n[1]);
        ptr[0] = n[0];
        ptr[1] = n[1];
        return  ptr;
}        
*/
//        int b;
//v7=v1;
#define ptr 4
#define const1 8 
        _asm  {
		
        	mov     eax, [esp+ptr]
        	push    ebx
        	mov     ebx, [esp+const1];cnt;
        	push	esi
        	mov     esi, [eax];c[0]
        	push    esi
        	mov     edi, [eax+4];c[1]
        	test	ebx, ebx
        	push	ebp
		jbe     short loc_401C15
 loop1:                            
                 mov     ebp, edi
                 mov     ecx, 1     
                 shr     ebp, 1Fh
                 mov     [esp+10h+const1], ebp;
                 mov     eax, esi
                 mov     edx, edi
                 xor     ebp, ebp       
                 
                 ;call    __allshl;            
                 shld    edx, eax, cl
                 shl     eax, cl

                 mov     ecx, [esp+10h+const1]
                 or      ebp, edx       
                                        
                 or      ecx, eax       
                 xor     edx, edx       
                 mov     esi, ecx       
                 mov     ecx, 0Bh        
                 mov     eax, esi       
                 mov     edi, ebp       
                 and     eax, 4         
                 
                 ;call    __allshl
                 shld    edx, eax, cl
                 shl     eax, cl

                 mov     ecx, esi       
                 xor     ebp, ebp       
                 and     ecx, 2000h     
                                        
                 xor     edx, ebp       
                 xor     eax, ecx       
                                        
                 mov     ecx, 12h       
                 
                ;call    __allshl
                 shld    edx, eax, cl
                 shl     eax, cl

                 ;
                 mov     ecx, esi       
                 xor     edx, ebp       
                 and     ecx, 80000000h 
                                        
                 xor     eax, ecx       
                 
                 mov     ecx, 1         
                 ;call    __allshl
                shld    edx, eax, cl
                shl     eax, cl


                 xor     esi, eax


                 xor     edi, edx

                 dec     ebx
                 jnz     short loop1
                 mov     eax, [esp+10h+ptr]
                 pop	 ebp		                 

         loc_401C15:                             
                 mov     [eax], esi
                 mov     [eax+4], edi
                 ;popad
                 ;pop     edi
                 ;pop     esi
                 ;pop     ebx
                 ;retn         

		

                 
		popad
                
                
                }
#undef ptr 
#undef const1
}

int main()
{	
        int knownArray[4] = {V0,V1,V2,V3};
	
	rolN_reverse(knownArray + 2, CV2 );
	rolN_reverse(knownArray +1, CV1);
	rolN_reverse(knownArray +0, CV0);
	
	//for(int i = 0; i < 4; i++) {
        //       printf(" 0x%X", knownArray[i]);
        //}
        
	return 0;
}
whyida 发表于 2017-9-5 21:01
代码测试通过,谢谢楼主。
[C] 纯文本查看 复制代码
#include <stdio.h>

#define V0 0x12345
#define V1 0X23456
#define V2 0X34567
#define V3 0X45678

#define CV0 0x255f35
#define CV1 0x24e918
#define CV2 0x2475dd

typedef unsigned __int32 uint32_t;
__declspec(naked) char * rolN_reverse(  uint32_t *Cptr,int Cconst1)
{	
/*
        uint32_t n[2], n_1[2];
        n[0] = ptr[0];
        n[1] = ptr[1];
        printf("[-]Get: %X %X\n", n[0], n[1]);
        for (int i = 0; i < cnt; i++) {
                n_1[0] = (n[0] >> 1 & 0x7fffffff)|((n[1]&1 ^ n[0]>>31^ n[0]>>13^ n[0]>>2)&1)<<31;

                n_1[1] = (n[1] >> 1 &0x7fffffff )|n[0]<<31;
                n[0] = n_1[0];
                n[1] = n_1[1];
        }
        printf("[-]Rev: %X %X\n", n[0], n[1]);
        ptr[0] = n[0];
        ptr[1] = n[1];
        return  ptr;
}        
*/
//        int b;
//v7=v1;
#define ptr 4
#define const1 8 
        _asm  {
		mov	eax, [esp+ptr]
		push	ebx
		mov	ebx, [esp+4+const1]
		push	esi
		mov	esi, [eax]
		push	edi
		mov	edi, [eax+4]
		test	ebx, ebx
		jbe	short loc_401C15
		push	ebp

loc_401BA5:				; CODE XREF: sub_401B90+7Ej
		mov	ebp, edi
		mov	ecx, 1
		shr	ebp, 1Fh
		mov	[esp+10h+const1], ebp
		mov	eax, esi
		mov	edx, edi
		xor	ebp, ebp

                ;call	__allshl
		shld    edx, eax, cl
                shl     eax, cl
                
		mov	ecx, [esp+10h+const1]
		or	ebp, edx
		or	ecx, eax
		xor	edx, edx
		mov	esi, ecx
		mov	ecx, 0Bh
		mov	eax, esi
		mov	edi, ebp
		and	eax, 4
		
		;call	__allshl

		shld    edx, eax, cl
                shl     eax, cl
                
		mov	ecx, esi
		xor	ebp, ebp
		and	ecx, 2000h
		xor	edx, ebp
		xor	eax, ecx
		mov	ecx, 12h
		
		;call	__allshl

		shld    edx, eax, cl
                shl     eax, cl
		
		mov	ecx, esi
		xor	edx, ebp
		and	ecx, 80000000h
		xor	eax, ecx
		mov	ecx, 1
		
		;call	__allshl

		shld    edx, eax, cl
                shl     eax, cl
		
		xor	esi, eax
		xor	edi, edx
		dec	ebx
		jnz	short loc_401BA5
		mov	eax, [esp+10h+ptr]
		pop	ebp

loc_401C15:				; CODE XREF: sub_401B90+12j
		mov	[eax], esi
		mov	[eax+4], edi
		pop	edi
		pop	esi
		pop	ebx
		retn

                }
#undef ptr 
#undef const1
}

int main()
{	
        uint32_t knownArray[4] = {V0,V1,V2,V3};
	
	rolN_reverse(knownArray + 0, CV0 );
	rolN_reverse(knownArray +1, CV1);
	rolN_reverse(knownArray +2, CV2);
	
	for(int i = 0; i < 4; i++) {
	       
               printf(" 0x%X", knownArray[i]);
        }
        
	return 0;
}
zbnysjwsnd8 发表于 2017-8-22 09:09
好厉害啊
对了 五星难度和问号的 哪个难度高一些?
 楼主| 6767 发表于 2017-8-22 09:15
本帖最后由 6767 于 2017-8-22 10:14 编辑
zbnysjwsnd8 发表于 2017-8-22 09:09
好厉害啊
对了 五星难度和问号的 哪个难度高一些?

你可以做做那些带问号的,给出你的评分啊
不加壳的话,难点就自我校验,暗桩,强力的混淆算法这几个了。




看了看160里面其他两个5星的,都是2000年左右写的,宏观上结构和现在这个差不多。
zbnysjwsnd8 发表于 2017-8-22 09:16
6767 发表于 2017-8-22 09:15
你可以做做那些带问号的,给出你的评分啊
不加壳的话,难点就自我校验,暗桩,强力的混淆算 ...

我做的几个带问号的注册方式都是serial的
好像都挺简单的
没有这个难(应该是我做的太少了
zbnysjwsnd8 发表于 2017-8-22 09:21
6767 发表于 2017-8-22 09:15
你可以做做那些带问号的,给出你的评分啊
不加壳的话,难点就自我校验,暗桩,强力的混淆算 ...

第90个和第132个
这个是我做的带问号的
我觉得没有楼主你玩的这个CM难
huangxu 发表于 2017-8-22 11:28
来学习一下,谢谢
ufo2273810 发表于 2017-8-22 16:10
谢谢分享。
Hmily 发表于 2017-8-22 17:55
就凭那手工图也要加个精华鼓励一下!
guaiguai 发表于 2017-8-22 18:51
来学习了
Avenshy 发表于 2017-8-22 19:26
这图画的真好
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-5-2 07:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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