首页
社区
课程
招聘
[原创]2019看雪CTF 晋级赛Q1 第5题
2019-3-24 12:18 6138

[原创]2019看雪CTF 晋级赛Q1 第5题

2019-3-24 12:18
6138

初步分析

没有多余的处理,直接可以进入对话框处理函数sub_402652(),看一下这个函数

int __cdecl sub_402652(HWND hDlg)
{
  int i; // esi
  signed __int8 v2; // cl
  int v3; // eax
  size_t v4; // eax
  int v5; // edi
  int len; // esi
  int v7; // eax
  char Result; // [esp+Ch] [ebp-614h]
  char v10; // [esp+Dh] [ebp-613h]
  __int16 v11; // [esp+109h] [ebp-517h]
  char v12; // [esp+10Bh] [ebp-515h]
  char pbuf; // [esp+10Ch] [ebp-514h]
  char v14; // [esp+10Dh] [ebp-513h]
  __int16 v15; // [esp+209h] [ebp-417h]
  char v16; // [esp+20Bh] [ebp-415h]
  unsigned __int8 pGloalStr; // [esp+20Ch] [ebp-414h]
  char v18; // [esp+20Dh] [ebp-413h]
  __int16 v19; // [esp+309h] [ebp-317h]
  char v20; // [esp+30Bh] [ebp-315h]
  CHAR Text; // [esp+30Ch] [ebp-314h]
  char v22; // [esp+30Dh] [ebp-313h]
  __int16 v23; // [esp+409h] [ebp-217h]
  char v24; // [esp+40Bh] [ebp-215h]
  char pOut; // [esp+40Ch] [ebp-214h]
  char v26; // [esp+40Dh] [ebp-213h]
  __int16 v27; // [esp+509h] [ebp-117h]
  char v28; // [esp+50Bh] [ebp-115h]
  char keyStr[12]; // [esp+50Ch] [ebp-114h]
  __int16 v30; // [esp+609h] [ebp-17h]
  char v31; // [esp+60Bh] [ebp-15h]
  CHAR String; // [esp+60Ch] [ebp-14h]
  __int16 v33; // [esp+60Dh] [ebp-13h]
  char v34; // [esp+60Fh] [ebp-11h]
  int lenOfKeyStr; // [esp+610h] [ebp-10h]
  size_t inputKeyLen; // [esp+614h] [ebp-Ch]
  char v37; // [esp+61Bh] [ebp-5h]
  int v38; // [esp+61Ch] [ebp-4h]

  String = 0;
  v33 = 0;
  v34 = 0;
  keyStr[0] = 0;
  memset(&keyStr[1], 0, 0xFCu);
  v30 = 0;
  v31 = 0;
  pGloalStr = 0;
  memset(&v18, 0, 0xFCu);
  v19 = 0;
  v20 = 0;
  Text = 0;
  memset(&v22, 0, 0xFCu);
  v23 = 0;
  v24 = 0;
  GetDlgItemTextA(hDlg, 1000, &String, 3);
  lenOfKeyStr = GetDlgItemTextA(hDlg, 1001, keyStr, 0xFF);
  initTextBufByType(0, &Text);                  // init Text -no,wrong.sn
  inputKeyLen = 0;
  v38 = 0;
  if ( lenOfKeyStr < 12 )                       // 输入字符串条件:开始不能是AA,第5,11位是V V ,长度大于12
    v38 = 1;
  if ( keyStr[0] == 'A' && keyStr[1] == 'A' )   // AA开始非法
    ++v38;
  if ( keyStr[5] != 'V' || keyStr[11] != 'V' )  // 5,11位V分割
    ++v38;
  for ( i = 0; i < lenOfKeyStr; ++i )
  {
    if ( i != 5 && i != 11 )
    {
      v2 = keyStr[i];
      v37 = keyStr[i];
      if ( dword_4082EC <= 1 )
      {
        v3 = *((_WORD *)off_4080E0 + v2) & 0x107;
      }
      else
      {
        v3 = _isctype(v2, 0x107);
        v2 = v37;
      }
      if ( !v3 )
      {
        v38 += 3;
        break;
      }
      v4 = inputKeyLen++;                       // index
      *(&pGloalStr + v4) = v2;
    }
  }
  if ( !v38 )
  {
    pOut = 0;
    memset(&v26, 0, 252u);
    v27 = 0;
    v28 = 0;
    Result = 0;
    memset(&v10, 0, 0xFCu);
    v11 = 0;
    v12 = 0;
    pbuf = 0;
    memset(&v14, 0, 0xFCu);
    v15 = 0;
    v16 = 0;
    v5 = String;
    initBase64String(80, &pbuf, 0x40u);         // ABCyVPGHTJKLMNOFQRSIUEWDYZgbc8sfah1jklmnopqret5v0xX9wi234u67dz+/
    setBase64Customer(&pbuf);
    len = base64Encoder(&pGloalStr, &pOut);     // key Base64加密
    base64Decoder((unsigned __int8 *)&pOut, &Result, len);// key base64解密
    if ( pOut )
    {
      if ( !memcmp(&Result, &pGloalStr, inputKeyLen) )// base64加密前和解密后相当
      {
        v7 = sub_4024E1(0x64, v5, (int)&pOut, len);// 0x64,O,加密key ,加密key长度
        initTextBufByType(v7, &Text);           // v7需要等于2,输入正确结果
      }
    }
  }
  MessageBoxA(hDlg, &Text, &Text, 0);
  return 0;
}

输入字符合法判断

从函数的前面部分可以知道几个输入key的条件:
1、长度大于12
2、前两位不能是AA
3、5,11位V分割
字符合法性判断完成后,进行字符串整理,将V从字符中去掉。

客制化Base64转换

base64 custom字串“ABCyVPGHTJKLMNOFQRSIUEWDYZgbc8sfah1jklmnopqret5v0xX9wi234u67dz+/”
将输入的key进行Base64加密再解密,加密前和解密后相等。这样看来字串长度是4的倍数了。

关键函数

满足base64转换条件后进入关键函数
v7 = sub_4024E1(0x64, v5, (int)&pOut, len);// 0x64,O,加密key ,加密key长度
initTextBufByType(v7, &Text); // v7需要等于2,输入正确结果
关键函数返回2,输入正确结果。

关键函数分析

关键函数内是大整数运算,我们先看一下大整数的数据结构
BigInt struc{
int sing //符号
int len //数据长度
int* pData //指向数据
}
好了,我们进入关键函数看看

int __cdecl sub_4024E1(int const0x64, int charO, int pEnInputKeyStr, int enKeyStrLen)
{
  signed int v4; // ebx
  int *buf_1; // edi
  int pbuf; // [esp+Ch] [ebp-1C0h]
  int buf[99]; // [esp+10h] [ebp-1BCh]
  BigInt bigData; // [esp+19Ch] [ebp-30h]
  BigInt bigIntKey; // [esp+1A8h] [ebp-24h]
  BigInt ret; // [esp+1B4h] [ebp-18h]
  BigInt p; // [esp+1C0h] [ebp-Ch]
  signed int b; // [esp+1D4h] [ebp+8h]
  int bingGo; // [esp+1E0h] [ebp+14h]

  pbuf = 0;
  memset(buf, 0, sizeof(buf));
  b = sub_40243F(const0x64, &pbuf);             // 产生多素数数组[3,5,7....0x47]
  newBigInt(&ret);
  newBigInt(&bigData);
  setBigInt(&ret, 0);                           // new String
  setBigInt(&bigIntKey, 0);
  v4 = 1;
  setBigInt(&p, 1);
  setBigInt(&bigData, pbuf);
  data2BigInt(&bigIntKey, pEnInputKeyStr, enKeyStrLen);// 将输入的key转换位大整数存储
  bingGo = getDataFormBigData(&ret);
  if ( b > 1 )
  {
    buf_1 = buf;
    while ( *buf_1 != charO )
    {
      if ( *buf_1 )
        createP((int)&p, (int)&p, *buf_1);      // 多素数相乘,得到p=0x41cd66acc237b22681a18067
      ++v4;
      ++buf_1;
      if ( v4 >= b )
        goto LABEL_9;
    }
    b = buf[v4];                                // 0x53
  }
LABEL_9:
  if ( checkBigInt(&bigIntKey, &bigData) >= 0 && checkBigInt(&bigIntKey, &p) <= 0 )// 2<key<p
  {
    quick_Mod(&ret, &bigIntKey, b, &p);         // 快速幂取模==2(2=key^0x53mod(p))
    if ( checkBigInt(&ret, &bigData) >= 0 && checkBigInt(&ret, &p) <= 0 )
      bingGo = getDataFormBigData(&ret);
  }
  StringFree((int)&ret);
  StringFree((int)&bigData);
  return bingGo;
}

这里是多素数相乘,得到p
createP((int)&p, (int)&p, *buf_1); // 多素数相乘,得到p=0x41cd66acc237b22681a18067
核心算法是快速幂取模,取模后的值为2.
2=key^0x53mod(p)

逆结果

多素数RSA密钥产生算法如下:
1.生成k个素数p1, p2, …, pk
2.求k个素数的乘积n=∏pi, i=1,2,…,k
3.求Euler函数值φ(n)=∏(pi-1)
4.选择指数e, 使得gcd(e,φ(n))=1
5.求指数d=e-1 mod φ(n)
6.输出公钥(e,n)和私钥(d,n)
多素数RSA 加密和解密算法与普通RSA的相同:
加密 c=me mod n
解密 m=cd mod n
现在我们已经知道
1、多素数数组[3,5,7....0x47]
2、多素数乘机0x41cd66acc237b22681a18067
3、φ(n)phi =((3-1)(5-1)10D19B3AB2BBDB0940000000..*(0x47-1))0x10D19B3AB2BBDB0940000000
4 、e=0x53
可以求出d= 0x6afde1a6c132be7eb2e43db

 

那么明文=2^0x6afde1a6c132be7eb2e43db Mod(0x41cd66acc237b22681a18067)==1555D30F38B0DBCAEC83C0F9
BASE64转换后为PEDIy9102dreadyu

 

以上计算可以使用该题作者在看雪上的工具,很方便。


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

最后于 2019-3-24 12:40 被ODPan编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (1)
雪    币: 5568
活跃值: (2991)
能力值: ( LV12,RANK:394 )
在线值:
发帖
回帖
粉丝
htg 4 2019-3-26 22:13
2
0
没有数学知识,真的是无法解题
游客
登录 | 注册 方可回帖
返回