2019 红帽杯 Re WP

目录

 

0x01 xx

1.准备

2.IDA打开

3.流程总结

4.脚本解密

5.get flag!

0x02  easyRE

1.准备

2.IDA打开

3.代码分析

4.get flag!

 0x03  calc

1准备

2.IDA打开

3.流程总结

4.get flag!

0x04 childRE

1.准备

2.IDA代码分析

3.流程总结

4.获取未修饰函数名

5.置换运算

6.get flag!

0x05 Snake

1.查看DLL文件

2.DLL文件分析

3.**求解

4.get flag!


0x01 xx

测试文件:https://www.lanzous.com/i7dyqhc

 

1.准备

2019 红帽杯 Re WP

获取信息

  • 64位文件

 

2.IDA打开

2019 红帽杯 Re WP

 

使用Findcrypt脚本可以看到

2019 红帽杯 Re WP

结合文件名是xx,因此猜测代码用到了xxtea加密方法

 

3.流程总结

因此,总的流程为:

  1. 判断输入的字符串的每个字符是否包含在"qwertyuiopasdfghjklzxcvbnm1234567890"中
  2. 取输入字符串的前4位字符,即"flag",扩展为16位,作为xxtea加密的秘钥key
  3. 将输入的字符串使用key加密,加密后的字符保存在字符数组v18,共24位字符
  4. 打乱v18数组,保存到v19数组中
  5. 将24位字符,每3位为一组,每一组异或值(具体看代码),得到新的加密字符串
  6. 将新的加密字符串与已经存在的字符串比较,相同即获得胜利

因此,只需要逆向变换,就能得到flag

使用动态调试,可以获取到已经存在的字符串

2019 红帽杯 Re WP

 

enc = 'CEBC406B7C3A95C0EF9B202091F70235231802C8E75656FA'

 

4.脚本解密

Python带了xxtea的包,不过我用的时候,一直提示我“ValueError: Need a 16-byte key.”,用rjust或者'\x00'*16补足了16位也不管用。

所以用了另外一种方法,借用了下面xxtea的文章:

 

参考文章:https://blog.****.net/weixin_41474364/article/details/84314674 

# encoding: utf-8
import struct

_DELTA = 0x9E3779B9

def _long2str(v, w):
    n = (len(v) - 1) << 2
    if w:
        m = v[-1]
        if (m < n - 3) or (m > n): return ''
        n = m
    s = struct.pack('<%iL' % len(v), *v)
    return s[0:n] if w else s

def _str2long(s, w):
    n = len(s)
    m = (4 - (n & 3) & 3) + n
    s = s.ljust(m, "\0")
    v = list(struct.unpack('<%iL' % (m >> 2), s))
    if w: v.append(n)
    return v

def encrypt(str, key):
    if str == '': return str
    v = _str2long(str, True)
    k = _str2long(key.ljust(16, "\0"), False)
    n = len(v) - 1
    z = v[n]
    y = v[0]
    sum = 0
    q = 6 + 52 // (n + 1)
    while q > 0:
        sum = (sum + _DELTA) & 0xffffffff
        e = sum >> 2 & 3
        for p in xrange(n):
            y = v[p + 1]
            v[p] = (v[p] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
            z = v[p]
        y = v[0]
        v[n] = (v[n] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[n & 3 ^ e] ^ z))) & 0xffffffff
        z = v[n]
        q -= 1
    return _long2str(v, False)

def decrypt(str, key):
    if str == '': return str
    v = _str2long(str, False)
    k = _str2long(key.ljust(16, "\0"), False)
    n = len(v) - 1
    z = v[n]
    y = v[0]
    q = 6 + 52 // (n + 1)
    sum = (q * _DELTA) & 0xffffffff
    while (sum != 0):
        e = sum >> 2 & 3
        for p in xrange(n, 0, -1):
            z = v[p - 1]
            v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
            y = v[p]
        z = v[n]
        v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
        y = v[0]
        sum = (sum - _DELTA) & 0xffffffff
    return _long2str(v, True)

def xor(x ,y):
    return ord(x) ^ ord(y)

# 转换为16进制
arr = 'CEBC406B7C3A95C0EF9B202091F70235231802C8E75656FA'.decode('hex')

dec = ''

# 因为加密时是正向加密,会用到加密之后的字符,因此解密需要逆向解密
for i in range(7,-1,-1):
    res = ''
    # 每3个为一组
    for j in range(3):
        temp = ord(arr[i*3+j])
        # 需要异或的值,例如第i组的值就是,arr[i*3+j]^(arr[n] for n in range(i))
        for m in range(i):
            temp ^= ord(arr[m])
        res += chr(temp)
    dec = res + dec

# 原来的v18到v19数组是被打乱排序了的
num = [2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]
enc = [0] * 24
# key需要是16位
key = 'flag'+'\x00'*12
for i in range(24):
    enc[num[i]] = dec[i]
dec2 = ''.join(enc)

dec3 = decrypt(dec2, key)
print dec4

2019 红帽杯 Re WP

 

5.get flag!

flag{CXX_and_++tea}

 

0x02  easyRE

测试文件:https://share.weiyun.com/5qzM6bU

 

1.准备

2019 红帽杯 Re WP

获取信息

  • 64位文件

 

2.IDA打开

signed __int64 sub_4009C6()
{
  char *v0; // rsi
  char *v1; // rdi
  signed __int64 result; // rax
  __int64 v3; // ST10_8
  __int64 v4; // ST18_8
  __int64 v5; // ST20_8
  __int64 v6; // ST28_8
  __int64 v7; // ST30_8
  __int64 v8; // ST38_8
  __int64 v9; // ST40_8
  __int64 v10; // ST48_8
  __int64 v11; // ST50_8
  __int64 v12; // ST58_8
  int i; // [rsp+Ch] [rbp-114h]
  char arraym[36]; // [rsp+60h] [rbp-C0h]
  char v15[32]; // [rsp+90h] [rbp-90h]
  int v16; // [rsp+B0h] [rbp-70h]
  char v17; // [rsp+B4h] [rbp-6Ch]
  char v18; // [rsp+C0h] [rbp-60h]
  char v19; // [rsp+E7h] [rbp-39h]
  char v20; // [rsp+100h] [rbp-20h]
  unsigned __int64 v21; // [rsp+108h] [rbp-18h]

  v21 = __readfsqword(0x28u);
  arraym[0] = 73;
  arraym[1] = 111;
  arraym[2] = 100;
  arraym[3] = 108;
  arraym[4] = 62;
  arraym[5] = 81;
  arraym[6] = 110;
  arraym[7] = 98;
  arraym[8] = 40;
  arraym[9] = 111;
  arraym[10] = 99;
  arraym[11] = 121;
  arraym[12] = 127;
  arraym[13] = 121;
  arraym[14] = 46;
  arraym[15] = 105;
  arraym[16] = 127;
  arraym[17] = 100;
  arraym[18] = 96;
  arraym[19] = 51;
  arraym[20] = 119;
  arraym[21] = 125;
  arraym[22] = 119;
  arraym[23] = 101;
  arraym[24] = 107;
  arraym[25] = 57;
  arraym[26] = 123;
  arraym[27] = 105;
  arraym[28] = 121;
  arraym[29] = 61;
  arraym[30] = 126;
  arraym[31] = 121;
  arraym[32] = 76;
  arraym[33] = 64;
  arraym[34] = 69;
  arraym[35] = 67;
  memset(v15, 0, sizeof(v15));
  v16 = 0;
  v17 = 0;
  v0 = v15;
  sub_4406E0(0LL, (__int64)v15);
  v17 = 0;
  v1 = v15;
  if ( sub_424BA0(v15) == 36 )
  {
    for ( i = 0; ; ++i )
    {
      v1 = v15;
      if ( i >= (unsigned __int64)sub_424BA0(v15) )
        break;
      if ( (unsigned __int8)(v15[i] ^ i) != arraym[i] )
      {
        result = 4294967294LL;
        goto LABEL_13;
      }
    }
    sub_410CC0("continue!");
    memset(&v18, 0, 0x40uLL);
    v20 = 0;
    v0 = &v18;
    sub_4406E0(0LL, (__int64)&v18);
    v19 = 0;
    v1 = &v18;
    if ( sub_424BA0(&v18) == 39 )
    {
      v3 = sub_400E44(&v18);
      v4 = sub_400E44(v3);
      v5 = sub_400E44(v4);
      v6 = sub_400E44(v5);
      v7 = sub_400E44(v6);
      v8 = sub_400E44(v7);
      v9 = sub_400E44(v8);
      v10 = sub_400E44(v9);
      v11 = sub_400E44(v10);
      v12 = sub_400E44(v11);
      v0 = off_6CC090;
      v1 = (char *)v12;
      if ( !(unsigned int)sub_400360(v12, off_6CC090) )
      {
        sub_410CC0("You found me!!!");
        v1 = "bye bye~";
        sub_410CC0("bye bye~");
      }
      result = 0LL;
    }
    else
    {
      result = 4294967293LL;
    }
  }
  else
  {
    result = 0xFFFFFFFFLL;
  }
LABEL_13:
  if ( __readfsqword(0x28u) != v21 )
    sub_444020(v1, v0);
  return result;
}

 

 

3.代码分析

首先有两次输入,第一次输入32位字符串,将每位字符异或后与已存在的marray数组比较,因此可以写出脚本,正确输入

arr = [73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,
       119,101,107,57,123,105,121,61,126,121,76,64,69,67]

dec = ''
for i in range(36):
    dec += chr(arr[i]^i)

print(dec)

Info:The first four chars are `flag`

 

第二次输入,将输入的字符串进行10次base64加密后,与已知的字符串比较,反向解密就行

enc = "Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ=="

for i in range(10):
    enc = enc.decode('base64')
print (enc)

https://bbs.pediy.com/thread-254172.htm

 

在第二次输入加密后对比的常量下面,还发现了一个常量,在sub_400D35函数中调用

2019 红帽杯 Re WP

__int64 __fastcall sub_400D35(__int64 a1, __int64 a2)
{
  __int64 v2; // rdi
  __int64 result; // rax
  unsigned __int64 v4; // rt1
  unsigned int v5; // [rsp+Ch] [rbp-24h]
  signed int i; // [rsp+10h] [rbp-20h]
  signed int j; // [rsp+14h] [rbp-1Ch]
  unsigned int v8; // [rsp+24h] [rbp-Ch]
  unsigned __int64 v9; // [rsp+28h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  v2 = 0LL;
  v5 = sub_43FD20(0LL) - qword_6CEE38;
  for ( i = 0; i <= 1233; ++i )
  {
    v2 = v5;
    sub_40F790(v5);
    sub_40FE60();
    sub_40FE60();
    v5 = (unsigned __int64)sub_40FE60() ^ 0x98765432;
  }
  v8 = v5;
  if ( ((unsigned __int8)v5 ^ byte_6CC0A0[0]) == 'f' && (HIBYTE(v8) ^ (unsigned __int8)byte_6CC0A3) == 'g' )
  {
    for ( j = 0; j <= 24; ++j )
    {
      v2 = (unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v8 + j % 4));
      sub_410E90(v2);
    }
  }
  v4 = __readfsqword(0x28u);
  result = v4 ^ v9;
  if ( v4 != v9 )
    sub_444020(v2, a2);
  return result;
}

两段异或,第一段异或,能够通过'flag'和已知数组反向解出v5

第二段异或。通过已知数组和v5解出flag

key = ''
enc1 = 'flag'
dec = ''
enc = [0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
for i in range(4):
    key += chr(enc[i] ^ ord(enc1[i]))
print (key)

for i in range(len(enc)):
    dec += chr(enc[i] ^ ord(key[i%4]))
print(dec)

2019 红帽杯 Re WP

 

4.get flag!

flag{Act1ve_Defen5e_Test}

 

 0x03  calc

测试文件:https://www.lanzous.com/i7frprg

 

1准备

2019 红帽杯 Re WP

获取信息

  • 64位文件 

 

2.IDA打开

2019 红帽杯 Re WP伪C代码

 

3.流程总结

整个过程,有三次输入,定义为变量x, y, z。在满足x < z and x > y的条件下,进行x**3+y**3+z**3=42,搜了一下有关“三次方42”的新闻

2019 红帽杯 Re WP

得到

(-80538738812075974)^3 + 80435758145817515^3 + 12602123297335631^3 = 42

根据x,y,z关系式得到

x=80435758145817515 
y=12602123297335631 
z=80538738812075974

将Sleep的时间全部改为0

2019 红帽杯 Re WP

 

2019 红帽杯 Re WP

 

写出脚本得到flag

2019 红帽杯 Re WP

 

 

4.get flag!

flag{951e27be2b2f10b7fa22a6dc8f4682bd}

 

0x04 childRE

测试文件:https://www.lanzous.com/i7h66wd

 

1.准备

2019 红帽杯 Re WP

  • 64位文件

 

2.IDA代码分析

2019 红帽杯 Re WP

 

3.流程总结

  • 因此总的运算流程就是:
  • 输入长度为31的字符串
  • 进行置换运算
  • 取消修饰函数名
  • 将未修饰函数名的商和余数与指定字符串比较

 

我们能够逆向操作来得到未修饰的函数名。

 

4.获取未修饰函数名

IDA动态调试

2019 红帽杯 Re WP

 

写出脚本

str1 = "([email protected]!08!6_0*[email protected]%%[email protected]=66!!974*3234=&0^3&[email protected]=&0908!6_0*&"
str2 = "55565653255552225565565555243466334653663544426565555525555222"
str3 = '[email protected]#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;,ASDFGHJKL:"ZXCVBNM<>?zxcvbnm,./'

name = ''

for i in range(62):
    name += chr(str3.index(str1[i]) + str3.index(str2[i])*23 )

print (name)

得到:private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)

 

使用C++写出一个上面函数的例子:

#include <iostream>

class R0Pxx {
public:
    R0Pxx() {
        My_Aut0_PWN((unsigned char*)"hello");
    }
private:
    char* __thiscall My_Aut0_PWN(unsigned char*);
};

char* __thiscall R0Pxx::My_Aut0_PWN(unsigned char*) {
    std::cout << __FUNCDNAME__ << std::endl;

    return 0;
}

int main()
{
    R0Pxx A;

    system("PAUSE");
    return 0;
}

得到:[email protected]@@[email protected]

 

5.置换运算

通过动态调试,发现乱序取值的数值是固定的,因此随便输入一组长度31的字符串(其中的字符不能重复)

2019 红帽杯 Re WP2019 红帽杯 Re WP

 

反向操作,写出脚本来解决flag

from hashlib import md5

str1 = 'abcdefghijklmnopqrstuvwxyz12345'
dec1 = '7071687273696474756A76776B656278796C7A316D6632336E34356F676361'.decode('hex')
serial = []

print dec1

for i in dec1:
    serial.append(str1.index(i))

print serial

name = '[email protected]@@[email protected]'
enc = [''] * 31

for i in range(31):
    enc[serial[i]] = name[i]
enc = ''.join(enc)

print enc

print md5(enc).hexdigest()

2019 红帽杯 Re WP

 

6.get flag!

flag{63b148e750fed3a33419168ac58083f5}

 

0x05 Snake

测试文件:https://www.lanzous.com/i7gol0d

 

Unity逆向

1.查看DLL文件

运行Snake,查看调用的DLL文件

2019 红帽杯 Re WP

 

2.DLL文件分析

使用ILSpy打开Interface.dll文件

发现了DLL文件使用的函数GameObject

2019 红帽杯 Re WP

 

使用IDA打开DLL文件

2019 红帽杯 Re WPGameObject

判断出GameObject函数传入的参数,最大应该是199,因此直接写程序,调用DLL文件,**求flag

 

3.**求解

开多个进程,同时求解。

#include <Windows.h>
#include <iostream>
#include <libloaderapi.h>

using namespace std;

int main(int argc, char* argv[])
{
    const char* funcName = "GameObject";
    HMODULE hDLL = LoadLibrary(TEXT("C:\\Users\\10245\\Desktop\\Snake\\Snake_Data\\Plugins\\Interface.dll"));
    if (hDLL != NULL)
    {
        cout << "Load Success!" << endl;
        typedef int(_cdecl *FuncPtr)(int);
        FuncPtr func = (FuncPtr)GetProcAddress(hDLL, funcName);
        func(atoi(argv[1]));    
    }
    else
    {
        cout << "Load Failed!" << endl;
    }


    system("PAUSE");
    return 0;
}

2019 红帽杯 Re WP

 

4.get flag!

flag{[email protected]}


作者:Hk_Mayfly 
出处:https://www.cnblogs.com/Mayfly-nymph/ 
个人博客:hkmayfly.com 
****:https://blog.****.net/qq_39542714 
如果你觉得博客对你有帮助的话,可以给博主一个(づ ̄3 ̄)づ╭❤~赞或者关注,谢谢!
博主目前大部分写作在博客园,欢迎大家来访,( ̄︶ ̄)↗也欢迎爱好写作的朋友和我交换友链。


附注:不支持转载!欢迎大家加我QQ,互相交流。Biubiubiu~顺便来关注我的公众号:Star Bottle叭!,哈哈哈!

       2019 红帽杯 Re WP                                2019 红帽杯 Re WP