一筐萝卜 发表于 2019-3-31 11:55

2019 上海“嘉韦思杯”逆向 writeup

### obfuse

32位ELF文件,无壳,载入IDA中通过关键字符串查找关键代码
![](https://s2.ax1x.com/2019/03/30/ADiSP0.png)
但是发现f5不好使,只能看汇编,首先输出“password:”,然后再从缓存区读取一串字符串,进入到sub\_8048580进行验证,若返回0,则输入的是错误的,若返回1则输入的是正确的
![](https://s2.ax1x.com/2019/03/30/ADipGV.png)

在sub\_8048580函数中是一位一位的check
```
_BOOL4 __cdecl sub_8048580(int a1, signed int a2)
{
signed int v2; // edx
char v3; // al
_BOOL4 result; // eax
char v5; //
char b20_1; //
char b1f_1; //
char b1e_1; //
char b1d_1; //
char b1c_1; //
char b1b_1; //
char b1a_1; //
char b19_1; //
char b18_1; //
char b17_1; //
char b16_1; //
char b15_1; //
char b14_1; //
char b13_0; //
char b12_0; //
char b11_0; //
char b10_0; //
char bf_0; //
char be_0; //
char bd_0; //
char bc_1; //
char bb_1; //
char ba_1; //
char b9_0; //
char b8_0; //
char b7_0; //
char b6_0; //
char b5_1; //
char b4_1; //
char b3_1; //
char b2_1; //
char b1_1; //
unsigned int v38; //

v38 = __readgsdword(0x14u);
v2 = a2;
while ( 2 )
{
    memset(v5, 0, 0x80u);
    v3 = *(_BYTE *)(a1 + v2);
    v5[(v3 + 64) % 128] = 1;
    if ( (unsigned __int8)(v3 - 10) <= 0x70u )
    {
      switch ( v3 )
      {
      case '\n':
          return v2 == 13 && ba_1 != 0;
      case '0':
          if ( v2 || !b9_0 )
            return 0;
          v2 = 1;
          continue;
      case '1':
          if ( v2 == 14 && b8_0 )
            goto LABEL_12;
          return 0;
      case '2':
          if ( v2 == 20 && b7_0 )
            goto LABEL_15;
          return 0;
      case '3':
          if ( v2 != 89 || !b6_0 )
            return 0;
          v2 = 90;
          continue;
      case '4':
          if ( v2 != 15 || !b5_1 )
            return 0;
          v2 = 16;
          continue;
      case '5':
          if ( v2 != 14 || !b4_1 )
            return 0;
LABEL_12:
          v2 = 15;
          continue;
      case '6':
          if ( v2 != 12 || !b3_1 )
            return 0;
          v2 = 13;
          continue;
      case '7':
          if ( v2 != 5 || !b2_1 )
            return 0;
          v2 = 6;
          continue;
      case '8':
          result = 0;
          if ( b1_1 )
            result = v2 == 33 || v2 == 2;
          return result;
      case '9':
          if ( v2 != 1 || !b1_1 )
            return 0;
          v2 = 2;
          continue;
      case 'a':
          if ( v2 != 35 || !b20_1 )
            return 0;
          v2 = 36;
          continue;
      case 'b':
          if ( v2 != 11 || !b1f_1 )
            return 0;
          v2 = 12;
          continue;
      case 'c':
          if ( v2 != 32 || !b20_1 )
            return 0;
          v2 = 33;
          continue;
      case 'd':
          if ( v2 != 3 || !b1e_1 )
            return 0;
          v2 = 4;
          continue;
      case 'e':
          if ( v2 != 7 || !b1d_1 )
            return 0;
          v2 = 8;
          continue;
      case 'f':
          if ( !b1c_1 || v2 != 8 && v2 != 4 )
            return 0;
          goto LABEL_53;
      case 'g':
          return v2 == 12 && b10_0 != 0;
      case 'h':
          if ( v2 != 13 || !b1b_1 )
            return 0;
          v2 = 14;
          continue;
      case 'i':
          if ( v2 != 9 || !b1a_1 )
            return 0;
          v2 = 10;
          continue;
      case 'j':
          if ( v2 != 10 || !b19_1 )
            return 0;
          v2 = 11;
          continue;
      case 'k':
          return v2 == 12 && b18_1 != 0;
      case 'l':
          if ( v2 != 19 || !b17_1 )
            return 0;
          v2 = 20;
          continue;
      case 'm':
          if ( v2 != 17 || !b16_1 )
            return 0;
          v2 = 18;
          continue;
      case 'n':
          return v2 == 18 && b16_1 != 0;
      case 'o':
          if ( !b15_1 || v2 != 6 && v2 != 28 )
            return 0;
LABEL_53:
          ++v2;
          continue;
      case 'p':
          if ( v2 != 30 || !b14_1 )
            return 0;
          v2 = 31;
          continue;
      case 'q':
          if ( v2 != 29 || !b13_0 )
            return 0;
          v2 = 30;
          continue;
      case 'r':
          if ( v2 != 20 || !b12_0 )
            return 0;
LABEL_15:
          v2 = 21;
          continue;
      case 's':
          if ( v2 != 25 || !b11_0 )
            return 0;
          v2 = 26;
          continue;
      case 't':
          return v2 == 24 && b12_0 != 0;
      case 'u':
          if ( v2 != 26 || !bf_0 )
            return 0;
          v2 = 27;
          continue;
      case 'v':
          if ( v2 != 2 || !be_0 )
            return 0;
          v2 = 3;
          continue;
      case 'w':
          if ( v2 != 6 || !bd_0 )
            return 0;
          v2 = 7;
          continue;
      case 'x':
          if ( v2 != 22 || !bc_1 )
            return 0;
          v2 = 23;
          continue;
      case 'y':
          if ( v2 != 23 || !bb_1 )
            return 0;
          v2 = 24;
          continue;
      case 'z':
          return v2 == 21 && b20_1 != 0;
      default:
          return 0;
      }
    }
    return 0;
}
}
```
根据switch中case的值和case中的if条件就可以反推出来正确的flag
#### flag:09vdf7wefijbk

### Auth.exe
32位的windows上可执行文件,无壳,先运行一下程序:
![](https://s2.ax1x.com/2019/03/30/ADiCxU.png)

同样也是载入IDA中通过关键字符串查找关键代码(main函数),本函数前面定义了一大堆数据,最后经过sub_401500处理

```
int __cdecl main(int argc, const char **argv, const char **envp)
{
const CHAR *v3; // ebx
HMODULE v4; // eax
void (__stdcall *v5)(HMODULE, LPCSTR); // eax
char v7; //
char v8; //
int v9; //
int v10; //
int v11; //
int v12; //
int v13; //
int v14; //
int v15; //
__int16 v16; //
int v17; //
int v18; //
int v19; //
int v20; //
int v21; //
int v22; //
int v23; //
int v24; //
int v25; //
int v26; //
int v27; //
int v28; //
int v29; //
char v30; //
int a_2; //
int v32; //
int v33; //
int v34; //
int v35; //
int v36; //
int v37; //
int v38; //
__int16 v39; //
int a_1; //
int v41; //
int v42; //
int v43; //
int v44; //
int v45; //
int v46; //
int v47; //
char v48; //
int v49; //
int v50; //
int v51; //
int v52; //
int v53; //
int v54; //
int v55; //
int v56; //
int v57; //
char v58; //
int v59; //
int v60; //
int v61; //
int v62; //
int v63; //
int v64; //
int v65; //
int v66; //
__int16 v67; //
int v68; //
int v69; //
char v70; //
int v71; //
int v72; //
int v73; //
int v74; //
int v75; //
int v76; //
int v77; //
int v78; //
int v79; //
int v80; //
int v81; //
int v82; //
int v83; //
int v84; //
int v85; //
int v86; //
int v87; //
__int16 v88; //
int *v89; //

v89 = &argc;
sub_402940();
puts(
    "            .   \n"
    "         _|_    ROBOTIC AUTHENTICATION SYSTEM\n"
    "    /\\/\\(. .)/\n"
    "    `||'   |#|\n"
    "   ||__.-\"-\"-.___   \n"
    "   `---| . . |--.\\\n"
    "         | : : |,||,\n"
    "         `..-..'\\/\\/\n"
    "          || ||   \n"
    "          || ||    \n"
    "         |__|__|\n");
v49 = 0x539;
v50 = 0x60646D51;
v51 = 0x64216472;
v52 = 0x7364756F;
v53 = 0x64697521;
v54 = 0x73686721;
v55 = 0x51217572;
v56 = 0x76727260;
v57 = 0x3B65736E;
v58 = 1;
a_1 = 0x60646D51;
v41 = 0x64216472;
v42 = 0x7364756F;
v43 = 0x64697521;
v44 = 0x73686721;
v45 = 0x51217572;
v46 = 0x76727260;
v47 = 0x3B65736E;
v48 = 1;
v59 = 0x60646D51;
v60 = 0x64216472;
v61 = 0x7364756F;
v62 = 0x64697521;
v63 = 0x62647221;
v64 = 0x21656F6E;
v65 = 0x72726051;
v66 = 0x65736E76;
v67 = 315;
a_2 = 0x60646D51;                           // Please enter the second Password
v32 = 0x64216472;
v33 = 0x7364756F;
v34 = 0x64697521;
v35 = 0x62647221;
v36 = 0x21656F6E;
v37 = 0x72726051;
v38 = 0x65736E76;
v39 = 315;
v68 = 0x6F6F3074;
v69 = 0x666D3367;
v70 = 3;
v28 = 0x6F6F3074;
v29 = 0x666D3367;
v30 = 3;
v71 = 0x6F73646A;
v72 = 0x33326D64;
v73 = 0x6D6D652F;
v74 = 0x13F0101;
v24 = 0x6F73646A;
v25 = 0x33326D64;
v26 = 0x6D6D652F;
v27 = 0x13F0101;
v75 = 0x57656540;
v76 = 0x6E756264;
v77 = 0x44656473;
v78 = 0x71646279;
v79 = 0x6F6E6875;
v80 = 0x656F6049;
v81 = 0x173646D;
v17 = 0x57656540;
v18 = 0x6E756264;
v19 = 0x44656473;
v20 = 0x71646279;
v21 = 0x6F6E6875;
v22 = 0x656F6049;
v23 = 0x173646D;
v82 = 0x21746E58;
v83 = 0x2F6F6876;
v84 = 0x6F6E4221;
v85 = 0x75607366;
v86 = 0x75606D74;
v87 = 0x726F6E68;
v88 = 0x120;
v10 = 0x21746E58;
v11 = 0x2F6F6876;
v12 = 0x6F6E4221;
v13 = 0x75607366;
v14 = 0x75606D74;
v15 = 0x726F6E68;
v16 = 0x120;
v9 = 0x539;
strcpy(v8, "r0b0RUlez!");
dword_40AD94 = (int)&v9;
dword_40ADA0 = (int)&v49;
dword_40AD8C = (char *)&a_1;
dword_40AD90 = (char *)&a_2;
dword_40AD98 = (int)&v28;
lpProcName = (LPCSTR)&v17;
lpModuleName = (LPCSTR)&v24;
dword_40ADA4 = (char *)&v10;
sub_401500(0);
v3 = lpProcName;
v4 = GetModuleHandleA(lpModuleName);
v5 = (void (__stdcall *)(HMODULE, LPCSTR))GetProcAddress(v4, v3);
v5((HMODULE)1, (LPCSTR)sub_40157F);
puts(dword_40AD8C);
scanf("%20s", &v7);
if ( !strcmp(&v7, v8) )
{
    puts("You passed level1!");
    sub_4015EA(0);
}
return 0;
}
```
在sub\_401500函数中对刚刚定义的数据的每一位都和1异或
![](https://s2.ax1x.com/2019/03/30/ADiFr4.png)
先把数据解密一下:
```
data1="516D6460726421646F756473217569642167687372752151607272766E73653B"
str1 =""
for x in range(0,len(data1),2):
      str1 += chr(eval("0x"+data1)^1)
print str1

data2 = "516D6460726421646F75647321756964217264626E6F652151607272766E73653B"

str2 =""
for x in range(0,len(data2),2):
      str2 += chr(eval("0x"+data2)^1)
print str2

data3 = "74306F6F67336D66"

str3 =""
for x in range(0,len(data3),2):
      str3 += chr(eval("0x"+data3)^1)
print str3

data4 = "6A64736F646D32332F656D6D"
str4 = ""
for x in range(0,len(data4),2):
      str4 += chr(eval("0x"+data4)^1)
print str4

data5 = "406565576462756E736465447962647175686E6F49606F656D6473"                           
str5 = ""
for x in range(0,len(data5),2):
      str5 += chr(eval("0x"+data5)^1)
print str5

data6 = "586E742176686F2F21426E6F66736075746D6075686E6F7220"
str6 = ""
for x in range(0,len(data6),2):
      str6 += chr(eval("0x"+data6)^1)
print str6
```
输出结果:
![](https://s2.ax1x.com/2019/03/30/ADikqJ.png)
发现是一些需要输出的字符串

接下来程序接收一个字符串,与字符串“r0b0RUlez!”进行比较,这是第一层限制,然后来到函数sub\_4015EA,在这个里面构造了一个异常,当程序走到这里的时候,发生异常而进行跳转,在跳转之前改变了一个数据,第二跳是在这个函数中的,那么我们就跟进第一条
![](https://s2.ax1x.com/2019/03/30/ADiVaR.png)

跟进之后来到一个函数中,再接收一个字符串,进入sub\_401547进行比较
![](https://s2.ax1x.com/2019/03/30/ADiZI1.png)

在sub\_401547函数中对字符串“u1nnf2lg”每一位都与2异或
![](https://s2.ax1x.com/2019/03/30/ADimPx.png)


解密得到“w3lld0ne”
```
flag = "u1nnf2lg"
real_flag =""
for x in range(len(flag)):
      real_flag+=chr(ord(flag)^2)
print real_flag
```

最后将字符串拼接起来
#### flag:r0b0RUlez!\_w3lld0ne

姬长信 发表于 2019-3-31 13:08

13号师傅也来华东吗?求带

一筐萝卜 发表于 2019-3-31 14:57

姬长信 发表于 2019-3-31 13:08
13号师傅也来华东吗?求带

不,我是第四,哈哈哈

一筐萝卜 发表于 2019-3-31 14:58

姬长信 发表于 2019-3-31 13:08
13号师傅也来华东吗?求带

不一定去,比赛发需要我们自费有点坑

姬长信 发表于 2019-3-31 15:24

一筐萝卜 发表于 2019-3-31 14:58
不一定去,比赛发需要我们自费有点坑

比赛我们学校可以报销哈哈

dd521q 发表于 2019-4-1 11:34

不错 很专业

52lxw 发表于 2019-5-9 12:52

能发下文件吗
页: [1]
查看完整版本: 2019 上海“嘉韦思杯”逆向 writeup