首页
社区
课程
招聘
[原创]湖湘杯 re shell 复现
发表于: 2021-11-18 02:13 8472

[原创]湖湘杯 re shell 复现

2021-11-18 02:13
8472

湖湘杯 re shell 复现

复现下觉得非常有意思的一道题,也是值得学习的一道题。

shell

题解比较多,懂得都懂,比赛时个人分析出来是pe映像切换技术+Debug Blocker,觉得十分有意思。但是由于提取出的exe文件,无法被ida正常识别出来,导致也无法分析关键代码,只能通过调试父进程的异常处理分析出了一个异或0x78。赛后等到了Mas0n师傅的wp,高实在是高,利用了ce作弊器可以附加进程的特性,通过ce作弊器来查看子进程的汇编代码,下面来复现这道题。

 

前面解密文件,pe映像切换的操作就不多看了,本人https://bbs.pediy.com/thread-269588.htm文章有讲到,需要注意的是这个exe是64位的,所以会有点不一样。

 

主要讲讲后面的部分,先用ce作弊器附加子进程,父进程断点要打在异常处理函数。

 

然后来看看父进程中的异常处理函数。

 

第一个异常int3

我们可以根据得到的信息去ce的内存浏览器去找相应代码,如下。

所以开始是异或0x78,然后继续在父进程打断点。

 

触发第一次无效指令异常。

接下来分析shell.exe+1035,利用ce右键的生成关系图,方便分析。

发现就是一些与运算和异或。

 

触发第二次无效指令异常。

接下来分析shell.exe+1242,发现就是比较密文。

 

用z3反解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from z3 import *
enc=[0x1E,0x15,0x1B,0x1C,0x07,0x4D,0x1F,0x1B,0x12,0x17,0x4B,0x44,0x47,0x58,0x12,0x47,0x58,0x58,0x47,0x5F,0x54,0x54,0x58,0x42,0x59,0x57,0x50,0x01,0x49,0x51,0x53,0x57,0x3D,0x6B,0x3E,0x6F,0x3D,0x6D,0x6C,0x3E,0x69,0x2C]
 
s = Solver()
flag = [BitVec('flag[%d]' % i, 8) for i in range(42)]
 
for i in range(42):
    flag[i]=flag[i]^0x78
 
for i in range(42):
    temp1 = (flag[i] & i) ^ 0xff
    temp2 = (flag[i] & temp1) ^ 0xff
    temp3 = (temp1 & i) ^ 0xff
    temp4 = (temp2 & temp3) ^ 0xff
    s.add(temp4==enc[i])
 
print(s.check())
m=s.model()
print(m)
#flag{0adbf973-d001-4896-962b-450e2d4a02a9}

Hideit

这道题还是比较简单,分析了一些时间就出了,ida打开,发现利用WriteProcessMemory向内存写入了一堆数据,函数逻辑被隐藏了,动调一直跟到关键函数,发现是将输入的字符转换为了两个4byte的数,然后进行一个魔改tea加密,写出解密脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<stdio.h>
 
void mydecrypt(unsigned int *code , unsigned int *key)
{
    unsigned int dealt=0x61C88647;
    unsigned int v0,v1,sum=0-dealt*32,i;
    __int64 e;
 
    v0=code[0];
    v1=code[1];
    for(i=0;i<32;i++)
    {
 
        e= (sum >> 2) & 3;
        v1 -= ((sum ^ v0) + (v0 ^ key[e ^ 1])) ^ (((16 * v0) ^ (v0 >> 3)) + ((v0 >> 5) ^ (4 * v0)));
        v0 -= ((sum ^ v1) + (v1 ^ key[e])) ^ (((16 * v1) ^ (v1 >> 3)) + ((v1 >> 5) ^ (4 * v1)));   
        sum+=dealt;
 
    }
    code[0]=v0;
    code[1]=v1;
}
 
int main()
{
    int i;
    unsigned int key[4]={0x72,0x202,0x13,0x13};
    unsigned int code[2]={0x1130BE1B,0x63747443};
 
 
    mydecrypt(code,key);
    for(i=0;i<2;i++)
    {
        printf("%c%c%c%c",*((char*)&code[i]+0),*((char*)&code[i]+1),*((char*)&code[i]+2),*((char*)&code[i]+3));
    }
    //dotitsit
}

然后继续调试,在调试过程中发现一个函数生成了和最后比较密文相同长度的数据,提取出来,得到

1
2
3
4
Xor[]={0x8D, 0xE2, 0x3D, 0xC2, 0x19, 0xF2, 0x2D, 0xCA, 0x18, 0x14,
  0xCF, 0x52, 0x77, 0x5A, 0x9C, 0x13, 0xAA, 0xCC, 0x04, 0x5B,
  0x92, 0xC1, 0x0C, 0x68, 0x45, 0x58, 0xF9, 0x47, 0x68, 0xD9,
  0x35, 0xC5}

然后异或得到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
 
int main()
{
    int i;
 
    int Xor[]={0x8D, 0xE2, 0x3D, 0xC2, 0x19, 0xF2, 0x2D, 0xCA, 0x18, 0x14,
  0xCF, 0x52, 0x77, 0x5A, 0x9C, 0x13, 0xAA, 0xCC, 0x04, 0x5B,
  0x92, 0xC1, 0x0C, 0x68, 0x45, 0x58, 0xF9, 0x47, 0x68, 0xD9,
  0x35, 0xC5};
      int flag[]={0xEB, 0x8E, 0x5C, 0xA5, 0x62, 0xB4, 0x1C, 0x84, 0x5C, 0x59,
  0xFC, 0x0D, 0x43, 0x3C, 0xAB, 0x20, 0xD8, 0x93, 0x33, 0x13,
  0xA1, 0x9E, 0x39, 0x00, 0x76, 0x14, 0xB5, 0x04, 0x58, 0x9D,
  0x06, 0xB8};
 
      for(i=0;i<32;i++)
      {
          printf("%c",Xor[i]^flag[i]);
      }
}
//flag{F1NDM3_4f73r_7H3_5h3LLC0D3}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 15565
活跃值: (16922)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
2
shell那道题确实挺好玩的,哈哈哈
2021-11-18 09:02
0
游客
登录 | 注册 方可回帖
返回
//