第五空间RE

2020-08-17 8,702

nop

该题使用如下的混淆手法,阻碍反编译实施:

image-20200624225630539.png

即将普通的相对转移流程改为使用push const+pop register+jmp register实现,只要手工还原即可还原代码,正常反编译:

image-20200624230432754.png

sub_804865B、sub_804857B、sub_80485**分别为基于环境变量、ptrace等反调试

除此之外,处理流程是输入是一个十进制整数,然后对该整数+1、+1、+0xCCCCCCCC、+1,之后进入sub_8048753:

image-20200624230729103.png

该函数把之前计算的整数作为地址,对该地址patch两个nop指令:

image-20200624230831024.png

通过查看汇编代码,该处jmp指令导致流程永远指向wrong:

image-20200624230905299.png

所以正确输入即0x8048765-1-0xCCCCCCCC-1-1=993507990

即:flag{993507990}

ManageCode

main调用主要check逻辑MainLogic2Check :

image-20200624232020409.png

image-20200624232108221.png

该函数为UnManaged Code,函数文件偏移 0x0019F920 :

image-20200624232214040.png


首先调用Managed Code,检查flag的格式是否为111111-111111-111111-11111111111111(1代表任意):

image-20200624231622273.png

sub_5A04D0将十六进制字符串转为十六进制:

image-20200624232324256.png

接着check477函数回到Managed Code层:

image-20200624231824443.png

Managed Code层又调用UnManaged Code层,文件偏移 0x000C6590 :

image-20200624232636390.png

终于定位到了真正的check逻辑,在UnManaged Code中的0x4C7190处(下面同时给出跟踪流程)

int __cdecl check477(unsigned __int8 *input)
{
 char v1; // dl
 int a_0; // esi
 int v3; // edi
 int v4; // eax
 int v5; // esi
 int v6; // ebx
 int v7; // esi
 int v8; // eax
 unsigned __int8 v9; // bl
 int v10; // edi
 int v11; // esi
 int v12; // edx
 int v13; // edi
 int v14; // esi
 int v15; // edi
 int v16; // esi
 int v17; // edi
 int v18; // esi
 int result; // eax
 int v20; // [esp+Ch] [ebp-34h]
 int v21; // [esp+10h] [ebp-30h]
 int v22; // [esp+14h] [ebp-2Ch]
 int v23; // [esp+18h] [ebp-28h]
 int v24; // [esp+1Ch] [ebp-24h]
 int v25; // [esp+24h] [ebp-1Ch]
 int v26; // [esp+28h] [ebp-18h]
 int v27; // [esp+2Ch] [ebp-14h]
 int v28; // [esp+30h] [ebp-10h]
 int v29; // [esp+34h] [ebp-Ch]
 int v30; // [esp+38h] [ebp-8h]
 int v31; // [esp+3Ch] [ebp-4h]

 v1 = 1;
 a_0 = *input;
 v3 = input[2];
 v31 = a_0;
 v28 = v3;
 v30 = input[1];
 if ( 0xFFF9DEB8 * a_0 != 0xFFBC91E8 )
   v1 = 0;
 if ( 191967 * input[1] + 473999 * a_0 != 23642821 )
   v1 = 0;
 v4 = 57125 * a_0;
 v5 = input[3];
 v6 = input[4];
 v29 = v5;
 v27 = v6;
 if ( v4 + 465507 * v30 - 207145 * v3 != 42831307 )
   v1 = 0;
 if ( 149773 * v5 + -488633 * v31 - 5245 * v30 - 280749 * v3 != -560637 )
   v1 = 0;
 if ( 381790 * v3 + 59135 * v6 + 130415 * v30 + 174205 * v5 - 83562 * v31 != 27764403 )
   v1 = 0;
 v7 = input[5];
 v26 = v7;
 v8 = 500139 * v6;
 v9 = v1;
 if ( 386908 * v31 + 465831 * v29 + v8 + 500998 * v7 + 474240 * v3 - 4838 * v30 != 119143813 )
   v9 = 0;
 v10 = input[6];
 v25 = v10;
 if ( 182991 * v29 + -200009 * v30 - 497601 * v31 - 153099 * v10 + 269682 * v27 + -269523 * v7 - 441164 * v28 != -52489521 )
   v9 = 0;
 v11 = input[7];
 v23 = v11;
 if ( -14894 * v11
    - 162386 * v31
    + 522547 * v29
    + 260922 * v26
    + 428523 * v28
    + 508037 * v27
    - 144626 * v30
    - 99507 * v10 != 67497415 )
   v9 = 0;
 v12 = input[8];
 if ( 51126 * v28
    + 145838 * v11
    + 362957 * v27
    + 43500 * v30
    + 308294 * v31
    + -375461 * v29
    - 174341 * v12
    - 394061 * v10
    - 65395 * v26 != -43306962 )
   v9 = 0;
 v13 = input[9];
 v24 = v13;
 if ( 350654 * v31
    + 495127 * v27
    + 434878 * v11
    - 75418 * v25
    - 43467 * v30
    + -521005 * v26
    - 226910 * v12
    - 215985 * v13
    - 121973 * v29
    - 446107 * v28 != -137046349 )
   v9 = 0;
 v14 = input[10];
 v22 = v14;
 if ( -318934 * v30
    - 25936 * v31
    - 341583 * v12
    + 320416 * v28
    + 339525 * v23
    - 81574 * v27
    - 502348 * v25
    - 294177 * v14
    - 363326 * v29
    - 391486 * v26
    - 248464 * v13 != -244744603 )
   v9 = 0;
 v15 = input[11];
 v21 = v15;
 if ( 81654 * v23
    + 432919 * v25
    + 110106 * v12
    - 507164 * v28
    - 467060 * v26
    + -384845 * v15
    - 197253 * v24
    - 354555 * v30
    - 16893 * v14
    - 254110 * v31
    - 479559 * v29
    - 50999 * v27 != -214023755 )
   v9 = 0;
 v16 = input[12];
 v20 = v16;
 if ( -117388 * v24
    - 227694 * v31
    + 457647 * v27
    + 293306 * v23
    + 101385 * v29
    + 293124 * v22
    + 92941 * v16
    + 496679 * v12
    + 79854 * v28
    + -81913 * v30
    - 507308 * v26
    - 3285 * v15
    - 71736 * v25 != 50059304 )
   v9 = 0;
 v17 = input[13];
 if ( 281406 * v28
    + 314118 * v27
    + -480916 * v23
    - 124091 * v17
    - 442447 * v22
    - 25649 * v31
    + 389372 * v16
    + 15089 * v29
    + 210603 * v25
    + 5 * (v12 + 17363 * v26 - 91574 * v21)
    - 469378 * v24
    - 117744 * v30 != -176657564 )
   v9 = 0;
 v18 = input[14];
 if ( 180059 * v25
    + 350603 * v31
    + -439557 * v21
    - 485708 * v28
    + 52520 * v24
    + 303697 * v27
    + 395976 * v22
    + 406658 * v26
    + -354103 * v17
    - 61339 * v20
    - 495692 * v30
    - 198340 * v29
    - 28153 * v12
    - 113385 * v23
    - 492085 * v18 != -48802225 )
   v9 = 0;
 result = v9;
 if ( 473763 * v12
    + 249640 * v25
    + 450341 * v29
    + 273347 * v17
    + 386739 * v30
    + 24246 * v26
    + 20430 * v21
    + 69055 * v27
    + 391476 * v22
    + 100872 * v23
    + 458039 * v20
    + 71004 * v24
    + -277369 * v28
    - 482854 * input[15]
    - 468152 * v31
    - 409044 * v18 != 224749784 )
   result = 0;
 return result;
}

Z3解方程即可:

from z3 import *
v = [BitVec('v%d'%i,32) for i in range(16)]

solver = Solver()

solver.add(0xFFF9DEB8 * v[0] == 0xFFBC91E8)
solver.add(191967 * v[1] + 473999 * v[0] == 23642821)
solver.add(57125 * v[0] + 465507 * v[1] - 207145 * v[2] == 42831307)
solver.add(149773 * v[3] + 4294478663 * v[0] - 5245 * v[1] - 280749 * v[2] == 4294406659)
solver.add(381790 * v[2] + 59135 * v[4] + 130415 * v[1] + 174205 * v[3] - 83562 * v[0] == 27764403)
solver.add(386908 * v[0] + 465831 * v[3] + 500139 * v[4] + 500998 * v[5] + 474240 * v[2] - 4838 * v[1] == 119143813)
solver.add(182991 * v[3] + 4294767287 * v[1] - 497601 * v[0] - 153099 * v[6] + 269682 * v[4] + 4294697773 * v[5] - 441164 * v[2] == 4242477775)
solver.add(4294952402 * v[7]
    - 162386 * v[0]
    + 522547 * v[3]
    + 260922 * v[5]
    + 428523 * v[2]
    + 508037 * v[4]
    - 144626 * v[1]
    - 99507 * v[6] == 67497415 )
solver.add(51126 * v[2]
    + 145838 * v[7]
    + 362957 * v[4]
    + 43500 * v[1]
    + 308294 * v[0]
    + 4294591835 * v[3]
    - 174341 * v[8]
    - 394061 * v[6]
    - 65395 * v[5] == 4251660334 )
solver.add(350654 * v[0]
    + 495127 * v[4]
    + 434878 * v[7]
    - 75418 * v[6]
    - 43467 * v[1]
    + 4294446291 * v[5]
    - 226910 * v[8]
    - 215985 * v[9]
    - 121973 * v[3]
    - 446107 * v[2] == 4157920947 )
solver.add(4294648362 * v[1]
    - 25936 * v[0]
    - 341583 * v[8]
    + 320416 * v[2]
    + 339525 * v[7]
    - 81574 * v[4]
    - 502348 * v[6]
    - 294177 * v[10]
    - 363326 * v[3]
    - 391486 * v[5]
    - 248464 * v[9] == 4050222693 )
solver.add(81654 * v[7]
    + 432919 * v[6]
    + 110106 * v[8]
    - 507164 * v[2]
    - 467060 * v[5]
    + 4294582451 * v[11]
    - 197253 * v[9]
    - 354555 * v[1]
    - 16893 * v[10]
    - 254110 * v[0]
    - 479559 * v[3]
    - 50999 * v[4] == 4080943541 )
solver.add(4294849908 * v[9]
    - 227694 * v[0]
    + 457647 * v[4]
    + 293306 * v[7]
    + 101385 * v[3]
    + 293124 * v[10]
    + 92941 * v[12]
    + 496679 * v[8]
    + 79854 * v[2]
    + 4294885383 * v[1]
    - 507308 * v[5]
    - 3285 * v[11]
    - 71736 * v[6] == 50059304 )
solver.add(281406 * v[2]
    + 314118 * v[4]
    + 4294486380 * v[7]
    - 124091 * v[13]
    - 442447 * v[10]
    - 25649 * v[0]
    + 389372 * v[12]
    + 15089 * v[3]
    + 210603 * v[6]
    + 5 * (v[8] + 17363 * v[5] - 91574 * v[11])
    - 469378 * v[9]
    - 117744 * v[1] == 4118309732 )
solver.add(180059 * v[6]
    + 350603 * v[0]
    + 4294527739 * v[11]
    - 485708 * v[2]
    + 52520 * v[9]
    + 303697 * v[4]
    + 395976 * v[10]
    + 406658 * v[5]
    + 4294613193 * v[13]
    - 61339 * v[12]
    - 495692 * v[1]
    - 198340 * v[3]
    - 28153 * v[8]
    - 113385 * v[7]
    - 492085 * v[14] == 4246165071 )
solver.add(473763 * v[8]
    + 249640 * v[6]
    + 450341 * v[3]
    + 273347 * v[13]
    + 386739 * v[1]
    + 24246 * v[5]
    + 20430 * v[11]
    + 69055 * v[4]
    + 391476 * v[10]
    + 100872 * v[7]
    + 458039 * v[12]
    + 71004 * v[9]
    + 4294689927 * v[2]
    - 482854 * v[15]
    - 468152 * v[0]
    - 409044 * v[14] == 224749784 )
for i in v:
   solver.add(i<0x100)
   solver.add(i>=0)
#solver.add(v[0]!=11)
if solver.check() == sat:
   m = solver.model()
   print m
   r_flag = ''
   for i in range(len(v)):
       r_flag += '%02x'%(m[v[i]].as_long().real)
   print r_flag
#flag{0b600c-3a198c-0e0891-9aa2ac765e0c7e}


rev

该题是rop vm,直接看main:

image-20200624233025974.png

跟进:

image-20200624233050183.png

直接把rsp改成了data的地址,也就是切换了栈的位置:

image-20200624233131013.png

data里面全是小gadget的地址,随便点开一个:

image-20200624233216029.png

我使用的方法是直接在vm入口处开启trace,打印所有执行过的指令,分析得到程序的处理流程,然后使用Z3解决问题(Z3方程就代表了程序的检查逻辑,故不再重复写了):

from z3 import *
solver = Solver()
v = [[BitVec('v%d'%(4*i+j),8) for j in range(4)] for i in range(4)]
data = [0x64,0x25,0x0F,0x6C,0x20,0x23,0x8A,0xDE,0x10,0x0E,0xA5,0xE1,0x43,0x37,0x11,0x53]
for i in range(16):
   data[i] ^= i

for g in range(4):
   group = v[g]
   b1 = group[0]
   b2 = group[1]
   b3 = group[2]
   b4 = group[3]
   solver.add((((2*b2)^b2)^((b3^b4)^(2*b1)))&0xff == data[g*4+0])
   solver.add((((2*b3)^b3)^((b1^b4)^(2*b2)))&0xff == data[g*4+1])
   solver.add((((2*b4)^b4)^((b1^b2)^(2*b3)))&0xff == data[g*4+2])
   solver.add((((2*b1)^b1)^((b2^b3)^(2*b4)))&0xff == data[g*4+3])
if solver.check() == sat:
   m = solver.model()
   res = [0]*16
   for i in range(4):
       for j in range(4):
           res[j*4+i] = chr(m[v[i][j]].as_long().real)
   print 'ctf{'+''.join(res)+'}'

由于该题出题失误,导致也可以用angr直接跑出结果,这里不在赘述。

philosopher

逆向程序要求输入MD5的md5等于给定:

int __cdecl main(int argc, const char **argv, const char **envp)
{
 __m128i *v3; // ecx
 int *v4; // edx
 unsigned int v5; // esi
 bool v6; // cf
 int result; // eax
 int v8[4]; // [esp+4h] [ebp-14h] BYREF

 puts("Are you a philosopher?");
 if ( argc <= 1 )
 {
   puts("Go away! You are not a philosopher!");
   result = 0;
 }
 else
 {
   v3 = MD5(argv[1]);
   v8[0] = 0x454C5C85;
   v8[1] = 0x25C370D1;
   v4 = v8;
   v8[2] = 0xB3C707F0;
   v5 = 12;
   v8[3] = 0x57635121;
   while ( v3->m128i_i32[0] == *v4 )
   {
     v3 = (__m128i *)((char *)v3 + 4);
     ++v4;
     v6 = v5 < 4;
     v5 -= 4;
     if ( v6 )
     {
       puts("We found a philosopher!");
       goto LABEL_6;
     }
   }
   puts("Nice try");
LABEL_6:
   result = 0;
 }
 return result;
}

去cmd5网站解密无果,后来查看程序资源:

image-20200624233943310.png

发现FL4G资源是个格式被破坏PNG:

image-20200624234037156.png

修复文件前四个字节即可:

image-20200624234100309.png

打开图片即可获得flag:

image-20200624234123111.png

run

发现题目exe可以直接解压:

image-20200624234728409.png

运行run得到一个tif文件,并且通过逆向run,发现tif文件后追加了一段数据:

image-20200624234909999.png

使用PS打开tif文件,发现移动图层可获得隐藏信息:

image-20200624235022619.png

脑洞该信息表示之前的加密算法,于是写出解密:

image-20200624235230044.png


本文作者:剑神

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/138050.html

Tags:
评论  (0)
快来写下你的想法吧!

剑神

文章数:2 积分: 60

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号