首页
社区
课程
招聘
[原创] 第五题:魅影舞姬
2019-9-17 10:48 2557

[原创] 第五题:魅影舞姬

2019-9-17 10:48
2557
首先对输入的长度限定
 std::string::string((std::string *)&serial);
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "please input your serial:\n");
  std::operator>><char,std::char_traits<char>,std::allocator<char>>(refptr__ZSt3cin, (std::string *)&serial);
  std::string::operator+=(&serial, "Welcome/to/this/very/simple/challenge");
  if ( (unsigned __int64)std::string::length((std::string *)&serial) > 85 )//输入加上一字符串的长度要<=85 即输入<=48
  {
    v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
    std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
    system("pause");
  }
然后调用check_fun函数进行检验,(函数内可以看到有生成随机数,输入作为种子,和btea算法,这里并不是关键,调试时过掉,先分析之后的算法)
_BOOL1 __fastcall check_fun(__int64 a1)
{
  char *v1; // rax
  int r3; // eax
  char v4; // [rsp+20h] [rbp-60h]
  unsigned int v5; // [rsp+9F0h] [rbp+970h]
  int v6; // [rsp+9F4h] [rbp+974h]
  int v7; // [rsp+A04h] [rbp+984h]
  int r2; // [rsp+A08h] [rbp+988h]
  unsigned int r1; // [rsp+A0Ch] [rbp+98Ch]

  v1 = (char *)std::string::operator[]((std::string *)a1, 0i64);
  std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::mersenne_twister_engine(
    &v4,
    (unsigned int)*v1);
  r1 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4);
  r2 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4);
  r3 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4);
  v7 = r3;
  v5 = r1;
  v6 = r3;
  btea(&v5, 2, &MD5_Constants_475020);
  return r2 - (v5 + v6) == 0xA504A8F7;
下面程序流程:
输入+“Welcome/to/this/very/simple/challenge”  中截取36位--> base64_decode
(3des)
     -->输入的[16:23]为key,对dest (解码结果的[18:])进行des_decode
     -->再以输入的[8:15]为key,对上一步des解密结果进行加密
          --> MD5(输入+“Welcome/to/this/very/simple/challenge” )               后面会判断md5值是否为44e4403b63620a2075d3fb2e0a6207d2
     -->最后以输入的[0:7]为key,再对上一步结果解密
-->加解密完成后,替换解码的[18:25]
-->进入主要的检验函数 check_de_Z9O0oOo0Oo0Ss
      des_decode_Z9Ooo0ooO0OPcS_S_(&Dest, &s_16_23, &Dest);
      des_encode_Z9Ooo0OO0ooPKcPcS1_(&Dest, &s_8_15, &Dest);
      Str_lens = strlen(Str);
      md5(&str_md5, Str, Str_lens);
      des_decode_Z9Ooo0ooO0OPcS_S_(&Dest, &s_0_7, &Dest);
      std::string::replace((std::string *)&de_serial, 18ui64, 8ui64, &Dest);
      std::string::string((std::string *)&v37, (const std::string *)&de_serial);
      check_de_Z9O0oOo0Oo0Ss((unsigned __int64)&v37);
      std::string::~string((std::string *)&v37);
我们进入 check_de_Z9O0oOo0Oo0Ss
__int64 __fastcall check_de_Z9O0oOo0Oo0Ss(unsigned __int64 a1)
{
  __int64 v2; // [rsp+0h] [rbp-80h]
  char v3; // [rsp+20h] [rbp-60h]
  char v4; // [rsp+30h] [rbp-50h]
  char v5; // [rsp+40h] [rbp-40h]
  char v6; // [rsp+50h] [rbp-30h]
  const std::string *a; // [rsp+80h] [rbp+0h]

  a = a1;
  std::string::substr((&v2 + 4), a1, 0i64, 6ui64);// 截取6个字符
  count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v3);// 第一个迷宫
  std::string::~string(&v3);
  modifi_maze_Z9O0oOo0Oo0ii(4, 5);              // 交换4,5行
  modifi_maze_Z9O0oOo0Oo0ii(9, 10);
  modifi_maze_Z9O0oOo0Oo0ii(10, 11);
  std::string::substr(&v4, a, 6ui64, 6ui64);
  count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v4);
  std::string::~string(&v4);
  modifi_maze_Z9O0oOo0Oo0ii(5, 7);
  modifi_maze_Z9O0oOo0Oo0ii(9, 12);
  modifi_maze_Z9O0oOo0Oo0ii(11, 12);
  std::string::substr(&v5, a, 12ui64, 6ui64);
  count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v5);
  std::string::~string(&v5);
  modifi_maze_Z9O0oOo0Oo0ii(2, 12);
  d_modifi_maze_Z9O0oOOo0o0ii(7, 9);            // 第7行替换第9行
  d_modifi_maze_Z9O0oOOo0o0ii(5, 3);
  d_modifi_maze_Z9O0oOOo0o0ii(5, 11);
  d_modifi_maze_Z9O0oOOo0o0ii(4, 7);
  d_modifi_maze_Z9O0oOOo0o0ii(4, 8);
  std::string::substr(&v6, a, 18ui64, 0xFFFFFFFFFFFFFFFFui64);
  count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v6);
  return std::string::~string(&v6);
}
查看迷宫的检验函数:
_BOOL8 __fastcall check_maze_Z9O0oO00ooOSs(std::string *a1)
{
  int v1; // eax
  _BOOL1 v2; // al
  signed int j; // [rsp+2Ch] [rbp-14h]
  unsigned __int64 i; // [rsp+30h] [rbp-10h]
  int v6; // [rsp+3Ch] [rbp-4h]
  std::string *v7; // [rsp+50h] [rbp+10h]

  v7 = a1;
  v6 = std::string::find(&str_2_Oooo0O0Oo, '@', 0i64);// size_t find(char c,size_t pos = 0)const;
                                                // 找‘@’,起始位置
  for ( i = 0i64; std::string::length(v7) > i; ++i )
  {
    for ( j = 6; j >= 0; j -= 2 )
    {
      v1 = (*std::string::operator[](v7, i) >> j) & 3;// 除64  16  4  1    与0011    保留低位
                                                // 即一个字节8位,先取高两位,···
      if ( v1 == 1 )
      {
        v6 += 13;                               // 下移动
      }
      else if ( v1 > 1 )
      {
        if ( v1 == 2 )
        {
          --v6;                                 // 左移动
        }
        else if ( v1 == 3 )
        {                                       // 3   右移动
          ++v6;
        }
      }
      else if ( !v1 )
      {
        v6 -= 13;                               // 0  上移
      }
      v2 = *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '-'
        && *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '#';
      if ( v2 )
        return 0i64;                            // 最后是#
    }
  }
  return *std::string::operator[](&str_2_Oooo0O0Oo, v6) == '#';
}
检验之后迷宫会进行变换:
modifi_maze_Z9O0oOo0Oo0ii          进行两个行的交换
_d_modifi_maze_Z9O0oOOo0o0ii    参数2的行用参数1的行替换

一共有4个迷宫,到这里就应该很明朗了,输入36位,进行base64解码,前3个6字节对应前3个迷宫,最后的8字节经过3des加解密,对应最后一个迷宫
迷宫脚本:
s = '**************@************-************--**----*****-***-**-*****-***#**-*****--*****-******-*****-******-------******-*-----******---**-*******-****--*****************'
print(len(s))
import numpy as np

def mod2h(x, a, b):#交换两行
    x[[a - 1, b - 1], :] = x[[b - 1, a - 1], :]
    return x

def mod1h(x, a, b):# b行用a行替换
    x[[b - 1], :] = x[[a - 1], :]
    return x


maze = list(s)
maze = np.array(maze).reshape(13, 13)
print('1-----------------------------------------------------------------')
print(maze)

print('2-----------------------------------------------------------------')
mod2h(maze, 4, 5)
mod2h(maze, 9, 10)
mod2h(maze, 10, 11)
t = maze.copy()
print(maze)

print("3-----------------------------------------------------------------")
mod2h(maze, 5, 7)
mod2h(maze, 9, 12)
mod2h(maze, 11, 12)
t = maze.copy()
print(maze)

print('4-----------------------------------------------------------------')
mod2h(maze, 2, 12)
mod1h(maze, 7, 9)
mod1h(maze, 5, 3)
mod1h(maze, 5, 11)
mod1h(maze, 4, 7)
mod1h(maze, 4, 8)
print(maze)
迷宫路线:
[0x55 ,0x75 ,0xFF ,0xF0 ,0x02 ,0xA5,#maze1
0x55, 0x75, 0x7C, 0xFF, 0x00, 0xA9,#mz2
0x55, 0x75, 0x7D, 0xFC, 0x30, 0xA8,#mz3
0x30,0x80,0x3,0x3f,0xfd,0x55,0x5a,0x80]#mz4
前三组base64编码便是输入的前部分
对mz4 要先进行des加解密
wp:
mz1=[0x55 ,0x75 ,0xFF ,0xF0 ,0x02 ,0xA5]#maze1
mz2=[0x55, 0x75, 0x7C, 0xFF, 0x00, 0xA9]#mz2
mz3=[0x55, 0x75, 0x7D, 0xFC, 0x30, 0xA8]#mz3
mz4=[0x30,0x80,0x3,0x3f,0xfd,0x55,0x5a,0x80]#mz4

import base64
k1=base64.b64encode(bytes(mz1))
k2=base64.b64encode(bytes(mz2))
k3=base64.b64encode(bytes(mz3))
keys=[k1,k2,k3]

from pyDes import des

t=des(k1).encrypt(bytes(mz4))
t=des(k2).decrypt(t)
t=des(k3).encrypt(t)

x=base64.b64encode(t)
keys.append(x)

flag=''
for x in keys:
    flag+=x.decode()

print(flag)

s=flag+ 'Welcome/to/this/very/simple/challenge'
import hashlib
m = hashlib.md5(s.encode()).hexdigest()
print(m)
print(m=='44e4403b63620a2075d3fb2e0a6207d2')

VXX/8AKlVXV8/wCpVXV9/DCogeWKJMtrmeY=






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

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