IT技术互动交流平台

SSCTF线上赛解题报告Part1(逆向部分)

作者:佚名  发布日期:2016-03-03 21:27:21

第二届SSCTF大赛上周落下帷幕,本系列是最终排名第三的Nu1L_XCTF团队带来的解题报告,分为逆向部分(Reverse)、杂项部分(Misc)、解密和溢出(Crypto&Exploit)、Web四个部分。

逆向部分(Reverse)
Re100
这题很简单,首先判断用户名是否等于secl-007

然后调用动态链接库中的getpl函数验证password,由于在函数中没有对password做处理,因此可以忽略中间的DES加密,输入39个字符或者修改寄存器的值,在最后判断的时候下断,动态调试下就能得到flag

flag为oty3eaP$g986iwhw32j%OJ)g0o7J.CG:
Re200
拿到程序打开运行,输入任意字符串后,发现一段Bad Apple的MV… 动画结束后有验证过程。
首先查壳,发现是加过UPX壳的。upx -d 脱掉之后开始分析程序:
发现在402800处是播放动画的代码,但其中有几条关键的ResumeThread,于是nop掉动画部分代码:

接下来根据ResumeThread处的代码找到了创建线程的位置:

继续分析这些线程 ,发现了验证Flag的位置,根据线程运行顺序可以反向写出解密代码:
脚本:
#!/usr/bin/env python2
# -*- coding:utf-8 -*-
import hashlib
import numpy as np
def u8(x):
    return np.uint8(x)
'''
  hash[0] = -3;
    hash[2] = -3;
      hash[1] = -59;
        hash[3] = -25;
          hash[5] = -25;
            hash[4] = -59;
              hash[6] = -57;
                hash[8] = -57;
                  hash[7] = -27;
                    hash[10] = -27;
                      hash[9] = -35;
                        hash[11] = -35;
                          hash[12] = 0;
'''
md5res = 'FBC4A31E4E17D829CA2242B2F893481B'.lower()
#print md5res
d = [253,197,253,231,197,231,199,229,199,221,229,221]
#d = [u8(c) for c in data]
#print d
for x in range(256):
    p = ''.join([chr(c^x) for c in d])
    md5 = hashlib.new('md5')
    for c in p:
 if ord(c) == 0: break
 md5.update(c)
    if md5.hexdigest() == md5res: print x
# key1 = 181
v0 = (181 - 1)^2
print v0
# v0 = 182
byte_404048 = [0x57,0x78,0x7d,0x3e,0x4a,0x4c,0x5c,0x35,0x2a,0x23,0x50,0x7f,0x57,0x78,0x55,0x64,0x4b,0x42,0x25,0x35,0x22,0x66,0x48]
for x2 in range(256):
 xored = [c^x2 for c in byte_404048]
 sum = 0
 for c in xored:
  if c == 0: break
  sum ^= c
 if sum == 182: print x2
print '-------'
# 152
for x3 in range(256):
 if ((x3^0x5a)+(x3^0x42)) == 152: print x3
print '------'
d3 = [0xF5, 0xD0, 0xDF, 0xDC, 0x99, 0xD8, 0xD5, 0xCE, 0xD8, 0xC0, 0xCA, 0x99, 0xD4, 0xD8, 0xD2, 0xDC, 0xCA, 0x99, 0xCC, 0xCA, 0x99, 0xDB, 0xD5, 0xD8, 0xDA, 0xD2, 0x99, 0xD8, 0xD7, 0xDD, 0x99, 0xDB,
0xD5, 0xCC, 0xDC, 0x95, 0xD8, 0xD7, 0xDD, 0x99, 0xCD, 0xD1, 0xD6, 0xCA, 0xDC, 0x99, 0xCE, 0xD1,
0xDC, 0xCB, 0xDC, 0x99, 0xCD, 0xD1, 0xDC, 0x99, 0xCE, 0xD6, 0xCC, 0xD7, 0xDD, 0x99, 0xD1, 0xD8,
0xDD, 0x99, 0xDB, 0xDC, 0xDC, 0xD7, 0x99, 0xCD, 0xD1, 0xDC, 0x99, 0xCA, 0xCD, 0xCB, 0xD6, 0xD7,
0xDE, 0xDC, 0xCA, 0xCD, 0x99, 0xCE, 0xD0, 0xD5, 0xD5, 0x99, 0xDB, 0xDC, 0xDA, 0xD6, 0xD4, 0xDC,
0x99, 0xD8, 0x99, 0xC9, 0xD5, 0xD8, 0xDA, 0xDC, 0x99, 0xCE, 0xD1, 0xDC, 0xCB, 0xDC, 0x99, 0xCE,

0xDC]
valid = []
for x4 in range(256):
 d3_xored = [x4^c for c in d3]
 xor_sum = 0
 for c in d3_xored:
  if c == 0: break
  xor_sum ^= c
 if (xor_sum^0x5a)+(xor_sum^0x42) == 152: valid.append(x4)
v = [c^0xC6 for c in valid]
n2 = [0x88, 0xEC, 0xFC, 0x9E, 0xB9, 0xFC, 0xB3, 0xAE, 0xFC, 0x92, 0xB3, 0xA8, 0xFC, 0x88, 0xB3, 0xFC,
0x9E, 0xB9, 0xF0, 0x88, 0xB4, 0xBD, 0xA8, 0xFC, 0xB5, 0xAF, 0xFC, 0x88, 0xB4, 0xB9, 0xFC, 0x8D,
0xA9, 0xB9, 0xAF, 0xA8, 0xB5, 0xB3, 0xB2]
v13_valid = []
for v13 in range(256):
 n2_xored = [v13^c for c in n2]
 n2xor_sum = 0
 for c in n2_xored:
  if c == 0: break
  n2xor_sum ^= c
 if n2xor_sum in v: v13_valid.append(v13)
print v13_valid
sums = []
for c in v13_valid:
 s3 = c ^ 0x6f
 s2 = c ^ 0x18
 s1 = c ^ 0x77
 s0 = c ^ 0x66
 if ((s0 + s1 + s2 + s3) & 0xFF) == 0xDC:
  sums.append([s0,s1,s2,s3])
ff = []
l = [0x63, 0x36, 0x37, 0x38, 0x64, 0x36, 0x67, 0x36, 0x34, 0x33, 0x30, 0x37, 0x67, 0x66, 0x34, 0x67,
0x60, 0x62, 0x32, 0x36, 0x33, 0x34, 0x37, 0x33, 0x67, 0x65, 0x33, 0x35, 0x62, 0x35, 0x60, 0x39]
for sum in sums:
 print sum
 f = [0]*32
 for i in range(4):
  s = sum[i]
  for j in range(8):
   if s & 1: f[i*8+7-j] = 1
   s >>= 1
 print f
 k = []
 for i in range(32):
  k.append(l[i]^f[i])
 print ''.join([chr(c) for c in k]) 
  
'''
l = [0x63, 0x36, 0x37, 0x38, 0x64, 0x36, 0x67, 0x36, 0x34, 0x33, 0x30, 0x37, 0x67, 0x66, 0x34, 0x67,
0x60, 0x62, 0x32, 0x36, 0x33, 0x34, 0x37, 0x33, 0x67, 0x65, 0x33, 0x35, 0x62, 0x35, 0x60, 0x39]
for i in range(32):
 l[i] ^= ff[i]
flag = ''.join([chr(c) for c in l])
print flag
flag = 'c678d6g65216fg5f`b263473fd24c4a8'
sum0 = 0
sum1 = 0
sum2 = 0
sum3 = 0
for i in range(8):
 sum0 = sum0 * 2 + (ord(flag[i])^l[i])
 sum1 = sum1 * 2 + (ord(flag[8+i])^l[8+i])
 sum2 = sum2 * 2 + (ord(flag[16+i])^l[16+i])
 sum3 = sum3 * 2 + (ord(flag[24+i])^l[24+i])
print sum0&0xff,sum1&0xff,sum2&0xff,sum3&0xff
'''
发现答案有多解,经过尝试发现 Flag 为:b669e6f65317ff5fac263573fe24b5a8
Re300
典型坑人题,真实的验证按钮是隐藏的。
首先拖入IDA分析,发现是MFC写程序。于是直接上xspy进行分析。

发现有两个OnCommand处理例程,而且id不相同。
由于习惯静态分析,于是直接上PE Explorer

发现id=03ec这个按钮是存在的。
于是直接使用ViewWizard修改控件属性
捕获窗口,右键定位到窗口列表,展开,右键捕获隐藏的按钮,点显示即可强制令其显示。

之后就显示了

当然,其实真正的罪魁祸首是在0x004015D0

调用了0x41276E这个库函数,其中调用ShowWindow将真实按钮的显示状态改成了SW_HIDE
于是之后点击这个真正的验证按钮,就来到了0x401FE0这里
然后进入验证函数0x401F80

在GetBody函数中,会首先判断输入的格式为SSCTF{32位},并将前后的SSCTF{和}去掉,保留中间的不封。
然后在GetHash部分中,会对输入进行变换

首先寻找’0’的所在位置,
接着按照这些已经计算出来的值进行变换,对大小写字母、数字分别处理

发现变换后的值和所在位置无关,仅和长度和’0’所在的位置有关,所以直接复制到vs中输出对应的变换。
之后在FinalVerify中会进行判断和输出结果。不过出题人好狠,一个可见字符串都不给,还用这么常见的加密手段,害的我这边数字公司一只都在拦截。。。

 

继续将hexrays的内容拷贝到vs中解密,得到分别是”Pls Try ag@in!”,” Y0u G0t 1t!” 和“b5h760h64R867618bBwB48BrW92H4w5r”
通过上步生成的表进行查表,得到原始内容为f5b760b64D867618fFeF48FdE92B4e5d
因此正确输入为SSCTF{f5b760b64D867618fFeF48FdE92B4e5d}
Flag为f5b760b64D867618fFeF48FdE92B4e5d
附上本题脚本:
 // re300.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
#include "atlstr.h"
int _tmain(int argc, _TCHAR* argv[])
{
 char v6[12]; // [sp+8h] [bp-4Ch]@1
 char Text[15]; // [sp+14h] [bp-40h]@1
 char target[33]; // [sp+24h] [bp-30h]@1
 target[4] = 7;
 target[7] = 7;
 target[11] = 7;
 target[13] = 7;
 target[2] = 89;
 target[17] = 115;
 target[19] = 115;
 target[22] = 115;
 target[6] = 89;
 target[23] = 67;
 target[31] = 67;
 target[0] = 83;
 target[1] = 4;
 target[3] = 6;
 target[5] = 1;
 target[8] = 5;
 target[9] = 99;
 target[10] = 9;
 target[12] = 6;
 target[14] = 0;
 target[15] = 9;
 target[16] = 83;
 target[18] = 70;
 target[20] = 5;
 target[21] = 9;
 target[24] = 102;
 target[25] = 8;
 target[26] = 3;
 target[27] = 121;
 target[28] = 5;
 target[29] = 70;
 target[30] = 4;
 target[32] = 0;
 v6[6] = 100;
 v6[9] = 100;
 Text[3] = 100;
 Text[7] = 100;
 v6[0] = 73;
 v6[1] = 32;
 v6[2] = 101;
 v6[3] = 48;
 v6[4] = 87;
 v6[5] = 32;
 v6[7] = 48;
 v6[8] = 33;
 v6[10] = 49;
 v6[11] = 0;
 Text[0] = 20;
 Text[1] = 40;
 Text[2] = 55;
 Text[4] = 16;
 Text[5] = 54;
 Text[6] = 61;
 Text[8] = 37;
 Text[9] = 35;
 Text[10] = 4;
 Text[11] = 45;
 Text[12] = 42;
 Text[13] = 101;
 Text[14] = 0;
 int v1 = 0;
 do
 {
  target[v1] ^= 0x31u;
  ++v1;
 } while (v1 32);
 int v2 = 0;
 if (strlen(v6) != 0)
 {
  do
  {
   v6[v2] ^= 0x10u;
   ++v2;
  } while (v2 strlen(v6));
 }
 int v3 = 0;
 if (strlen(Text) != 0)
 {
  do
  {
   Text[v3] ^= 0x44u;
   ++v3;
  } while (v3 strlen(Text));
 }
 char tihuan_low[27];
 char tihuan_cap[27];
 for (char i = 'a'; i'z'; i++){
  char ori_chr = i;
  BOOL target = 0;
  if (ori_chr > '9' || ori_chr '0')
  {                                         // 非数字
   if (ori_chr > 'z' || ori_chr 'a')
   {                                       // 非小写
    if (ori_chr 'Z' && ori_chr >= 'A')
     ori_chr -= 'A';                     // 大写转字母表中顺序
   }
   else
   {
    ori_chr -= 'a';                       // 小写转字母表中顺序
    target = 1;
   }
   int v9 = (28 + 5 * ori_chr) % 26 + ((28 + 5 * ori_chr) % 26 0 ? 26 : 0);//
   // 是字母
   if (target)
   {                                       // 是小写字母
    if (target == 1)
     v9 = (char)(v9 + 'a');
   }
   else
   {                                       // 是大写字母

 

    v9 = (char)(v9 + 'A');
   }
   //printf("%c - %c ", i, (char)v9);
   tihuan_low[i - 'a'] = (char)v9;
   tihuan_cap[i - 'a'] = toupper(v9);
  }
 }
 tihuan_low[26] = 0;
 tihuan_cap[26] = 0;
 //char tihuan_cap[] = "CHMRWBGLQVAFKPUZEJOTYDINSX";
 //char tihuan_low[] = "chmrwbglqvafkpuzejotydinsx";
 //char target[] = "b5h760h64R867618bBwB48BrW92H4w5r";
 char *out = new char[strlen(target)+1];
 out[strlen(target)] = 0;
 for (int i = 0; i strlen(target); i++){
  if (target[i] >= '0' && target[i] '9'){
   out[i] = target[i];
  }
  else if (target[i] >= 'a' && target[i] 'z'){
   for (int j = 0; j strlen(tihuan_low); j++){
    if (tihuan_low[j] == target[i]){
     out[i] = 'a' + j;
    }
   }
  }
  else if (target[i] >= 'A' && target[i] 'Z'){
   for (int j = 0; j strlen(tihuan_cap); j++){
    if (tihuan_cap[j] == target[i]){
     out[i] = 'A' + j;
    }
   }
  }
 }
 /*HCRYPTHASH phHash;
 HCRYPTPROV phProv;
 DWORD pdwDataLen;
 CString tempstr;
 
 UINT64 true_answ = 0;
 char target[] = { 0x48,0x50,0xB7,0x44,0x6B,0xBB,0x20,0xAA,0xD1,0x40,0xE7,0xB0,0xA9,0x64,0xA5,0x7D };
 for (UINT64 seed = 2453148193;; seed += 4294967296){
  BOOL bRight = TRUE;
  tempstr.Format("%I64d", seed);
  printf("%s ", tempstr.GetBuffer());
  if (CryptAcquireContextA(&phProv, 0, 0, 1u, CRYPT_VERIFYCONTEXT))
  {
   if (CryptCreateHash(phProv, CALG_MD5, 0, 0, &phHash))
   {
    if (CryptHashData(phHash, (BYTE *)tempstr.GetBuffer(), tempstr.GetLength(), 0))
    {
     char pbData[64];
     memset(pbData, 0, 64);
     pdwDataLen = 64;
     CryptGetHashParam(phHash, HP_HASHVAL, (BYTE *)pbData, &pdwDataLen, 0);
     for (int i = 0; i
 
 system("pause");
 return 0;
}
 // re300.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
#include "atlstr.h"
int _tmain(int argc, _TCHAR* argv[])
{
 char v6[12]; // [sp+8h] [bp-4Ch]@1
 char Text[15]; // [sp+14h] [bp-40h]@1
 char target[33]; // [sp+24h] [bp-30h]@1
 target[4] = 7;
 target[7] = 7;
 target[11] = 7;
 target[13] = 7;
 target[2] = 89;
 target[17] = 115;
 target[19] = 115;
 target[22] = 115;
 target[6] = 89;
 target[23] = 67;
 target[31] = 67;
 target[0] = 83;
 target[1] = 4;
 target[3] = 6;
 target[5] = 1;
 target[8] = 5;
 target[9] = 99;
 target[10] = 9;
 target[12] = 6;
 target[14] = 0;
 target[15] = 9;
 target[16] = 83;
 target[18] = 70;
 target[20] = 5;
 target[21] = 9;
 target[24] = 102;
 target[25] = 8;
 target[26] = 3;
 target[27] = 121;
 target[28] = 5;
 target[29] = 70;
 target[30] = 4;
 target[32] = 0;
 v6[6] = 100;
 v6[9] = 100;
 Text[3] = 100;
 Text[7] = 100;
 v6[0] = 73;
 v6[1] = 32;
 v6[2] = 101;
 v6[3] = 48;
 v6[4] = 87;
 v6[5] = 32;
 v6[7] = 48;
 v6[8] = 33;
 v6[10] = 49;
 v6[11] = 0;
 Text[0] = 20;
 Text[1] = 40;
 Text[2] = 55;
 Text[4] = 16;
 Text[5] = 54;
 Text[6] = 61;
 Text[8] = 37;
 Text[9] = 35;
 Text[10] = 4;
 Text[11] = 45;
 Text[12] = 42;
 Text[13] = 101;
 Text[14] = 0;
 int v1 = 0;
 do
 {
  target[v1] ^= 0x31u;
  ++v1;
 } while (v1 32);
 int v2 = 0;
 if (strlen(v6) != 0)
 {
  do
  {
   v6[v2] ^= 0x10u;
   ++v2;
  } while (v2 strlen(v6));
 }
 int v3 = 0;
 if (strlen(Text) != 0)
 {
  do
  {
   Text[v3] ^= 0x44u;

 

   ++v3;
  } while (v3 strlen(Text));
 }
 char tihuan_low[27];
 char tihuan_cap[27];
 for (char i = 'a'; i'z'; i++){
  char ori_chr = i;
  BOOL target = 0;
  if (ori_chr > '9' || ori_chr '0')
  {                                         // 非数字
   if (ori_chr > 'z' || ori_chr 'a')
   {                                       // 非小写
    if (ori_chr 'Z' && ori_chr >= 'A')
     ori_chr -= 'A';                     // 大写转字母表中顺序
   }
   else
   {
    ori_chr -= 'a';                       // 小写转字母表中顺序
    target = 1;
   }
   int v9 = (28 + 5 * ori_chr) % 26 + ((28 + 5 * ori_chr) % 26 0 ? 26 : 0);//
   // 是字母
   if (target)
   {                                       // 是小写字母
    if (target == 1)
     v9 = (char)(v9 + 'a');
   }
   else
   {                                       // 是大写字母
    v9 = (char)(v9 + 'A');
   }
   //printf("%c - %c ", i, (char)v9);
   tihuan_low[i - 'a'] = (char)v9;
   tihuan_cap[i - 'a'] = toupper(v9);
  }
 }
 tihuan_low[26] = 0;
 tihuan_cap[26] = 0;
 //char tihuan_cap[] = "CHMRWBGLQVAFKPUZEJOTYDINSX";
 //char tihuan_low[] = "chmrwbglqvafkpuzejotydinsx";
 //char target[] = "b5h760h64R867618bBwB48BrW92H4w5r";
 char *out = new char[strlen(target)+1];
 out[strlen(target)] = 0;
 for (int i = 0; i strlen(target); i++){
  if (target[i] >= '0' && target[i] '9'){
   out[i] = target[i];
  }
  else if (target[i] >= 'a' && target[i] 'z'){
   for (int j = 0; j strlen(tihuan_low); j++){
    if (tihuan_low[j] == target[i]){
     out[i] = 'a' + j;
    }
   }
  }
  else if (target[i] >= 'A' && target[i] 'Z'){
   for (int j = 0; j strlen(tihuan_cap); j++){
    if (tihuan_cap[j] == target[i]){
     out[i] = 'A' + j;
    }
   }
  }
 }
 /*HCRYPTHASH phHash;
 HCRYPTPROV phProv;
 DWORD pdwDataLen;
 CString tempstr;
 
 UINT64 true_answ = 0;
 char target[] = { 0x48,0x50,0xB7,0x44,0x6B,0xBB,0x20,0xAA,0xD1,0x40,0xE7,0xB0,0xA9,0x64,0xA5,0x7D };
 for (UINT64 seed = 2453148193;; seed += 4294967296){
  BOOL bRight = TRUE;
  tempstr.Format("%I64d", seed);
  printf("%s ", tempstr.GetBuffer());
  if (CryptAcquireContextA(&phProv, 0, 0, 1u, CRYPT_VERIFYCONTEXT))
  {
   if (CryptCreateHash(phProv, CALG_MD5, 0, 0, &phHash))
   {
    if (CryptHashData(phHash, (BYTE *)tempstr.GetBuffer(), tempstr.GetLength(), 0))
    {
     char pbData[64];
     memset(pbData, 0, 64);
     pdwDataLen = 64;
     CryptGetHashParam(phHash, HP_HASHVAL, (BYTE *)pbData, &pdwDataLen, 0);
     for (int i = 0; i
 
 system("pause");
 return 0;

 

}
Re400
脱壳,去花后开始分析
第一层在00401d25()函数里,如下图

图中byte_41279c是输入的字符串,然后经过change_xor()函数变换后与固定一组字符比较,即V11,V11两次异或3相当于没变。

第一步密码:[Xi`An4YeCaoAnQuanGongSi][HP]
V11:
a3=[0x7C,0xCD,0x01,0x97,0x06,0x6F,0x2C,0x29,0xFC,0x31,0x09,0xDC,0x1D,0xF5,0x8F,0x7D,0xDE,0x30,0xB6,0x49,0xFD,0x0A,0xD9,0x89,0xFD,0x9F,0x4D,0x7D,0xA2]
由V11可知,密码长度为29,于是随便输入29位数后,修改内存为0×00,此时a3的值就位异或对象a2的值,如下图

整理出来
b2=[0x27,0x95,0x68,0xF7,0x47,0x01,0x18,0x70,0x99,0x72,0x68,0xB3,0x5C,0x9B,0xDE,0x08,0xBF,0x5E,0xF1,0x26,0x93,0x6D,0x8A,0xE0,0xA0,0xC4,0x05,0x2D,0xFF]
与V11对应位异或,写脚本得到最后的结果为:
[Xi`An4YeCaoAnQuanGongSi][HP]
第二步:
从sub_401473()里读入第二步密码,然后调用sub_401119()来验证。

验证部分如下图,if条件固定了密码的前两位”[/”和最后两位/]””。 Sub_401c7d是对索引做浮点数运算,最后求和得到V7,判断57.1时走向正确流程,由此可推出密码2的长度为20。
然后将V46与密码长度异或后得到的值与V8比较。则通过V8与密码长度异或就可以求出V46即第二步密码。
V8:
a4=[0x3B,0x4C,0x7D,0x7A,0x5A,0x7D,0x75,0x7A,0x5F,0x61,0x75,0x7D,0x58,0x71,0x6A,0x3B]
与0×14异或后得到/XinNianKuaiLe~/。
最后拼接前两位于后两位   [//XinNianKuaiLe~//]
执行完sub_401473程序走到sub_401066弹出一段图片和音乐,一个白板转啊转。然后看DisplayFunc的函数sub_402921(),修改参数1.0为0 ,就可以得到FLAG了,glRotatef(angle, 0.0, 0.0, 1.0)。
最后FLAG图片如下:

然后就队友们各种猜,最后得到FLAG为
FLAG{ETIJVA3E96GXZ+HP+E380}
Re500—–比赛时未作出来,赛后做
做了Re400的旋转以为脑洞很大了,谁知道这题的脑洞真的。。。
这题用了debug blocker反调试技术,子进程会开启一个服务器,父进程会读取[SsCTF]Re.txt的内容向子进程发送,子进程会处理收到的数据并把结果发送给父进程,之后会读取Port.txt的内容作为端口,向自身发送UDP请求,其中的一些细节后面会说到。
题目一共有三层,第一层的关键是解密sub_401945函数,队友写程序将所有的密钥情形都输出,发现0xE9时解得有意义代码,解密完后的函数是

其中sub_40153B是对接收的数据做base64编码,然后与VURQ比较,由此得出第一层的密码为UDP,而这个字符串的ASCII码相加也正好等于0xE9,这一层Port.txt的内容为2016,记录两个地方的值,后面会用到
第一个地方

第二个地方

这一层的EncryptKey为0xE9,v16为2016,因此第一个地方异或后得到
pr0oihsn1eMgylf@J88JJJ88J8J8J8JJJ8888JJJJJJJ8J8J8JJ88J8888J8JJJ888JJJJ8J8888888J
buf为05162b4d677092b4,这一层会输出It is UDP!。
第二层,分析服务器处理接收数据的函数得到

由此这一层要让ret返回1,能返回1的只能是sub_4019B5函数

其中的sub_40170B是TEA加密算法,key为[0x44434241, 0x48474645, 0x4C4B4A49, 0x504F4E4D],密文为38 95 3C F0 4E 5A 57 89 6F 84 3E 01 BC 50 C8 5C 6A 7C 59 67EC BA 77 FD 73 2E,而TEA加密是8个字节一组,生成的密文长度是8的倍数,但这组的密文长度是26,最后两个字符不做处理,对前24个字节进行解密再加上最后两个字符得到第二层的密码为
WoyaoDuanKouHaoHeFlag,Pls. ,端口号为2447,这一层的EncryptKey为2446,之前上面那两处地方的第一处地方的数据为

 


第二处的buf为0d1e23456f789abc,这一层输出Port:2447。
最后要让ret返回2,而这个需要调用sub_4017CF函数
这个函数中是对接收到的数据进行哈夫曼编码,最后与0000110100011110001000110100010111101101011011110111100011111001101010111100对比,那对应关系在哪呢,开始脑洞
前面得到了
pr0oihsn1eMgylf@J88JJJ88J8J8J8JJJ8888JJJJJJJ8J8J8JJ88J8888J8JJJ888JJJJ8J8888888J

05162b4d677092b4 没用
0d1e23456f789abc
上面图片中的后面部分看成高低电平,高电平代表1,低电平代表0,按照pr0oihsn1eMgylf@这个顺序得到对应的编码:

按照这个对应关系解码最后对比的哈夫曼编码可以得到flag为fl@gMyengl1shisp0or,最后输出0K!You Got 1t!。
还有上面的0d1e23456f789abc转换成二进制表示为:

按照这个解码得到fl@gMyen1ship0or,但是这个比正确的flag少了3个字符。
Tag标签: 部分   报告  
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规