首页
社区
课程
招聘
[原创]第七题 声名远扬WP
2021-12-2 11:09 13966

[原创]第七题 声名远扬WP

2021-12-2 11:09
13966

程序使用了兼容模式下32位代码与64位代码的混合执行的技术。

.text:00B2D88E 6A 00                                   push    0
.text:00B2D890 8B 5D 10                                mov     ebx, [ebp+arg_8]
.text:00B2D893 53                                      push    ebx
.text:00B2D894 8B 4D 0C                                mov     ecx, [ebp+arg_4]
.text:00B2D897 51                                      push    ecx
.text:00B2D898 8B 4D 08                                mov     ecx, [ebp+arg_0]
.text:00B2D89B 51                                      push    ecx
.text:00B2D89C 6A 00                                   push    0
.text:00B2D89E 8D 4D EC                                lea     ecx, [ebp+var_14]
.text:00B2D8A1 51                                      push    ecx
.text:00B2D8A2 FF 5D F4                                call    fword ptr [ebp+var_C] //进入IA-32e模式

当执行到.text:00B2D8A2 时,栈内存ebp+var_C如下:

Stack[000057AC]:012FEDB4 dd offset byte_B256F0   //远调用目标绝对地址
Stack[000057AC]:012FEDB8 dd 33h            //远调用CS段选择子

当前CS段选择子为23h, 调用后的CS段选择子0x33(64位用户代码段). 

0xB256F0所指的代码是64位代码,将其导出为二进制文件,使用IDA将其作为64位代码进行分析:

seg000:0000000000000000 sub_0           proc far
seg000:0000000000000000
seg000:0000000000000000 arg_0           = qword ptr  10h
seg000:0000000000000000 arg_8           = qword ptr  18h
seg000:0000000000000000 arg_10          = qword ptr  20h
seg000:0000000000000000 arg_18          = qword ptr  28h
seg000:0000000000000000 arg_20          = qword ptr  30h
seg000:0000000000000000 arg_28          = qword ptr  38h
seg000:0000000000000000
seg000:0000000000000000                 mov     rdi, [rsp+arg_0]
seg000:0000000000000005                 mov     rsi, [rsp+arg_8]
seg000:000000000000000A                 mov     r11, 1
seg000:0000000000000011                 lea     r10, [rsp+arg_10]
seg000:0000000000000016                 cmp     rsi, 1
seg000:000000000000001A                 jb      short loc_50
seg000:000000000000001C                 mov     rcx, [rsp+arg_10]
seg000:0000000000000021                 cmp     rsi, 2
seg000:0000000000000025                 jb      short loc_50
seg000:0000000000000027                 mov     rdx, [rsp+arg_18]
seg000:000000000000002C                 cmp     rsi, 3
seg000:0000000000000030                 jb      short loc_50
seg000:0000000000000032                 mov     r8, [rsp+arg_20]
seg000:0000000000000037                 cmp     rsi, 4
seg000:000000000000003B                 jb      short loc_50
seg000:000000000000003D                 mov     r9, [rsp+arg_28]
seg000:0000000000000042                 mov     rax, rsi
seg000:0000000000000045                 shl     rax, 3
seg000:0000000000000049                 add     r10, rax
seg000:000000000000004C                 sub     r10, 8
seg000:0000000000000050
seg000:0000000000000050 loc_50:                                 ; CODE XREF: sub_0+1A↑j
seg000:0000000000000050                                         ; sub_0+25↑j ...
seg000:0000000000000050                 cmp     rsi, r11
seg000:0000000000000053                 jb      short loc_62
seg000:0000000000000055                 mov     rax, [r10]
seg000:0000000000000058                 push    rax
seg000:0000000000000059                 sub     r10, 8
seg000:000000000000005D                 inc     r11
seg000:0000000000000060                 jmp     short loc_50
seg000:0000000000000062 ; ---------------------------------------------------------------------------
seg000:0000000000000062
seg000:0000000000000062 loc_62:                                 ; CODE XREF: sub_0+53↑j
seg000:0000000000000062                 call    rdi             //实际验证函数
seg000:0000000000000064                 shl     rsi, 3
seg000:0000000000000068                 add     rsp, rsi
seg000:000000000000006B                 mov     rbx, [rsp+8]
seg000:0000000000000070                 mov     [rbx], rax
seg000:0000000000000073                 retf                    //返回兼容模式

通过分析堆栈,可知验证函数为0xB255AC(同样为64位代码),导出分析:

__int64 __fastcall sub_B255AC(char *seri, __int64 )
{
  //...
  //初始化
  v27 = 44;
  v4 = 0;
  *(__m128i *)v28 = _mm_load_si128((const __m128i *)0xB25408);
  *(__m128i *)&v28[32] = _mm_load_si128((const __m128i *)0xB253F8);
  *(__m128i *)&v28[16] = _mm_load_si128((const __m128i *)0xB25418);
  //序列号生成
  do
  {
    v5 = v4 - 52;
    v6 = v4++;
    v28[v6] ^= v5;
  }
  while ( v4 < v27 );
  v28[v27] = 0;
  //序列号输入检查
  v7 = 0;
  chr = *seri;
  if ( *seri )
  {
    v9 = seri;
    do
    {
      if ( chr != v9[v28 - seri] )
        break;
      ++v9;
      ++v7;
      chr = *v9;
    }
    while ( *v9 );
  }
  v10 = v7;
  i = 0;
  v24 = -48;
  if ( seri[v10] == v28[v10] )
  {
    //验证成功
  }
  else
  {
    //验证失败
  }
  return 0i64;
}

算法较简单,静态分析即可,若想进行动态调试,可配置bochs调试(注意依赖数据也须导入到数据库),配置如下:

序列号算法:

//.idc
auto bytes = get_bytes(0xB25408, 0x10, 1);
bytes = bytes + get_bytes(0xB25418, 0x10, 1);
bytes = bytes + get_bytes(0xB253F8, 0x10, 1);

auto i = 0;
for(i = 0; i<44; i++){
    auto v = ord(bytes[i]) ^ ((i - 52) & 0xff);
    msg("%02X ", (v & 0xff));
    bytes[i] = v;
}
bytes[i] = '\x00';

msg("\n%s\n", bytes);
//GYldGg-iIoJlPX9hPXpjPqfdEY21B01TBTzeGqfKNR!!


输入的序列号需要进行类似base64的编码,编码函数位于.text:00B2E530,因此需要做对应的解码操作:

//.idc
auto seri = "GYldGg-iIoJlPX9hPXpjPqfdEY21B01TBTzeGqfKNR";
auto sseri = "";
auto chr = 0;
auto bits = 0;
auto result = 0;
auto tree = ECX;                        //调试拿到tree地址
auto i = 0;
auto j = 0;
for(i = 0; i < strlen(seri); i++){
    auto found = -1;    
    for(j = 0; j <= 0x40; j++){
        auto c = j;
        auto sc = bsearch(tree, &c);    //APPCALL .text:00B2E970 ; void *__thiscall bsearch(void *bin_tree, char *chr)
        //msg("%02X ", byte(sc));
        if(ord(seri[i]) == byte(sc)){
            found = j;
            break;        
        }    
    }
       
    if(found == -1){
        msg("\n###EXCEPTION %d %d %X\n", i, strlen(seri), ord(seri[i]));
        break;
    }
    else{    
        bits = bits + 6;
        chr = chr << 6;
        chr = chr | found;          
        while(bits >= 8){
            auto v = chr >> (bits - 8);
            chr = chr - (v << (bits - 8));
            bits = bits -8;
            msg("%02X ", (v & 0xFF));          
        }
    }
}
msg("\nDONE bits = %d, chr = %02X\n", bits, chr);
/*
66 6C 61 67 7B 32 30 32 31 2D 31 30 2D 30 34 2D 79 61 6E 67 79 61 6E 67 62 75 64 65 79 69 7D 
DONE bits = 4, chr = 00
*/

解码得到序列号为:

flag{2021-10-04-yangyangbudeyi}



[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回