首页
社区
课程
招聘
[原创]第三题 write up by 青蛙Mage
发表于: 2019-3-24 16:14 6676

[原创]第三题 write up by 青蛙Mage

2019-3-24 16:14
6676
使用工具:IDA pro 7.0,JS反混淆,delphi反编译工具(IDR)
大体框架,用iefarme画出UI......
运行起来内存里有一段比较可疑的东西
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<script>
    function sptWBCallback(spt_wb_id, spt_wb_name, optionstr) {
        url = '#sptWBCallback:id=';
        url = url + spt_wb_id + ';
eventName=' + spt_wb_name;
        if (optionstr) url = url + ';params=optionstr';
        location = url;
    }
    eval(function(p, a, c, k, e, d) {
        e = function(c) {
            return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? StringfromCharCode(c + 29) : c.toString(36))
        };
        if (!''.replace(/^/, String)) {
            while (c--) d[e(c)] = k[c] || e(c);
            k = [function(e) {
                return d[e]}];
            e = function() {
                return '\\w+'
            };
            c = 1
        };
        while (c--)
        if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
        document.write(p)
        return p
    }('a 6() {    f="n";3 = 8.5.l.q;
  c (3.d(f) ==0) {        g=3.h;        b=f.h;o(3.p(b,g));    } 9 {        4("r!<" + 3 + "> e j i 2 ;-)");m "1";    }}a k(){  4("7!");}', 62, 28, '|1234|GUID|a|alert|all|ckpswd|congratulations|document|else|function|i|if|indexOf|is|key|l|length|my|not|ok|pswd|return|simpower91|sptWBCallback|substring|value|wrong'.split('|'), 0, {}))
</script>
//解混淆以后 意思就是 
比较输入的内容  如果有 simpower91 再将后面的几位 作为参数输入sptWBCallback,否则就会用vba画个框高速你错误。
做到这里就断了,完全断了,你无论后面输入什么都不给提示
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<script>
    function sptWBCallback(spt_wb_id, spt_wb_name, optionstr) {
        url = '#sptWBCallback:id=';
        url = url + spt_wb_id + ';
eventName=' + spt_wb_name;
        if (optionstr) url = url + ';params=optionstr';
        location = url;
    }
    eval(function(p, a, c, k, e, d) {
        e = function(c) {
            return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? StringfromCharCode(c + 29) : c.toString(36))
        };
        if (!''.replace(/^/, String)) {
            while (c--) d[e(c)] = k[c] || e(c);
            k = [function(e) {
                return d[e]}];
            e = function() {
                return '\\w+'
            };
            c = 1
        };
        while (c--)
        if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
        document.write(p)
        return p
    }('a 6() {    f="n";3 = 8.5.l.q;
  c (3.d(f) ==0) {        g=3.h;        b=f.h;o(3.p(b,g));    } 9 {        4("r!<" + 3 + "> e j i 2 ;-)");m "1";    }}a k(){  4("7!");}', 62, 28, '|1234|GUID|a|alert|all|ckpswd|congratulations|document|else|function|i|if|indexOf|is|key|l|length|my|not|ok|pswd|return|simpower91|sptWBCallback|substring|value|wrong'.split('|'), 0, {}))
</script>
//解混淆以后 意思就是 
比较输入的内容  如果有 simpower91 再将后面的几位 作为参数输入sptWBCallback,否则就会用vba画个框高速你错误。
做到这里就断了,完全断了,你无论后面输入什么都不给提示
柳暗花明又一村,既然脚本语言是动态执行,那么至少要捕获我输的什么内容吧,GO
摸鱼下断,在所有带strlen之类意思的函数下断,终于找到你了
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11)
{
  int v11; // ebx
  int v12; // eax
  int v13; // edx
  Classes::TStrings *v14; // esi
  int v15; // ST14_4
  int v16; // ST10_4
  unsigned int v18; // [esp-14h] [ebp-34h]
  void *v19; // [esp-10h] [ebp-30h]
  int *v20; // [esp-Ch] [ebp-2Ch]
  int v21; // [esp-8h] [ebp-28h]
  int v22; // [esp-4h] [ebp-24h]
  int v23; // [esp+0h] [ebp-20h]
  int v24; // [esp+4h] [ebp-1Ch]
  int v25; // [esp+8h] [ebp-18h]
  char v26[4]; // [esp+Ch] [ebp-14h]
  int v27; // [esp+10h] [ebp-10h]
  int System::AnsiString; // [esp+14h] [ebp-Ch]
  int v29; // [esp+18h] [ebp-8h]
  int v30; // [esp+1Ch] [ebp-4h]
  int savedregs; // [esp+20h] [ebp+0h]

  System::AnsiString = 0;
  v27 = 0;
  *(_DWORD *)v26 = 0;
  v25 = 0;
  v24 = 0;
  v23 = 0;
  v22 = a4;
  v21 = a5;
  v29 = a3;
  v30 = a2;
  v11 = a1;
  v20 = &savedregs;
  v19 = &loc_4921D1;
  v18 = __readfsdword(0);
  __writefsdword(0, (unsigned int)&v18);
  Variants::__linkproc__ VarToLStr(&v27, a11);
  if ( sub_465C88(&str__sptWBCallback_[1], v27) > 0 )
  {
    *a6 = -1;
    Variants::__linkproc__ VarToLStr(&System::AnsiString, a11);
    unknown_libname_60(System::AnsiString);
    v12 = System::__linkproc__ LStrCopy(&System::AnsiString);
    LOBYTE(v12) = 1;
    unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, (unsigned int)v26);
    System::__linkproc__ LStrLAsg(&System::AnsiString, *(_DWORD *)v26);
    LOBYTE(v13) = 1;
    v14 = (Classes::TStrings *)unknown_libname_33(cls_Classes_TStringList, v13);
    (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v14 + 44))(v14, System::AnsiString);
    if ( *(_WORD *)(v11 + 50) )
    {
      Classes::TStrings::GetValue(v14, (const int)&str_params[1], (int)&v25);
      v15 = v25;
      Classes::TStrings::GetValue(v14, (const int)&str_eventName[1], (int)&v24);
      v16 = v24;
      Classes::TStrings::GetValue(v14, (const int)&str_id[1], (int)&v23);
      (*(void (__fastcall **)(_DWORD, int, int, int))(v11 + 48))(*(_DWORD *)(v11 + 52), v23, v16, v15);
    }
  }
  if ( *(_WORD *)(v11 + 58) )
    (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v11 + 56))(
      *(_DWORD *)(v11 + 60),
      v30,
      v29,
      a11,
      a10,
      a9,
      a8,
      a7,
      a6);
  __writefsdword(0, v18);
  v20 = (int *)&loc_4921D8;
  return System::__linkproc__ LStrArrayClr(&v23, 6);
}
重要的流程,通过about:blank#sptcallback+str 作为后续输入,跟着一路会检测你是否是输入四位然后到另一个关键函数
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11)
{
  int v11; // ebx
  int v12; // eax
  int v13; // edx
  Classes::TStrings *v14; // esi
  int v15; // ST14_4
  int v16; // ST10_4
  unsigned int v18; // [esp-14h] [ebp-34h]
  void *v19; // [esp-10h] [ebp-30h]
  int *v20; // [esp-Ch] [ebp-2Ch]
  int v21; // [esp-8h] [ebp-28h]
  int v22; // [esp-4h] [ebp-24h]
  int v23; // [esp+0h] [ebp-20h]
  int v24; // [esp+4h] [ebp-1Ch]
  int v25; // [esp+8h] [ebp-18h]
  char v26[4]; // [esp+Ch] [ebp-14h]
  int v27; // [esp+10h] [ebp-10h]
  int System::AnsiString; // [esp+14h] [ebp-Ch]
  int v29; // [esp+18h] [ebp-8h]
  int v30; // [esp+1Ch] [ebp-4h]
  int savedregs; // [esp+20h] [ebp+0h]

  System::AnsiString = 0;
  v27 = 0;
  *(_DWORD *)v26 = 0;
  v25 = 0;
  v24 = 0;
  v23 = 0;
  v22 = a4;
  v21 = a5;
  v29 = a3;
  v30 = a2;
  v11 = a1;
  v20 = &savedregs;
  v19 = &loc_4921D1;
  v18 = __readfsdword(0);
  __writefsdword(0, (unsigned int)&v18);
  Variants::__linkproc__ VarToLStr(&v27, a11);
  if ( sub_465C88(&str__sptWBCallback_[1], v27) > 0 )
  {
    *a6 = -1;
    Variants::__linkproc__ VarToLStr(&System::AnsiString, a11);
    unknown_libname_60(System::AnsiString);
    v12 = System::__linkproc__ LStrCopy(&System::AnsiString);
    LOBYTE(v12) = 1;
    unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, (unsigned int)v26);
    System::__linkproc__ LStrLAsg(&System::AnsiString, *(_DWORD *)v26);
    LOBYTE(v13) = 1;
    v14 = (Classes::TStrings *)unknown_libname_33(cls_Classes_TStringList, v13);
    (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v14 + 44))(v14, System::AnsiString);
    if ( *(_WORD *)(v11 + 50) )
    {
      Classes::TStrings::GetValue(v14, (const int)&str_params[1], (int)&v25);
      v15 = v25;
      Classes::TStrings::GetValue(v14, (const int)&str_eventName[1], (int)&v24);
      v16 = v24;
      Classes::TStrings::GetValue(v14, (const int)&str_id[1], (int)&v23);
      (*(void (__fastcall **)(_DWORD, int, int, int))(v11 + 48))(*(_DWORD *)(v11 + 52), v23, v16, v15);
    }
  }
  if ( *(_WORD *)(v11 + 58) )
    (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v11 + 56))(
      *(_DWORD *)(v11 + 60),
      v30,
      v29,
      a11,
      a10,
      a9,
      a8,
      a7,
      a6);
  __writefsdword(0, v18);
  v20 = (int *)&loc_4921D8;
  return System::__linkproc__ LStrArrayClr(&v23, 6);
}
重要的流程,通过about:blank#sptcallback+str 作为后续输入,跟着一路会检测你是否是输入四位然后到另一个关键函数
int __usercall sub_4734B0@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15)
{
  unsigned int v15; // et0
  int (__fastcall *v16)(unsigned int *); // ST10_4
  unsigned int v18; // [esp+10h] [ebp-30h]
  int v19; // [esp+30h] [ebp-10h]
  void **v20; // [esp+34h] [ebp-Ch]
  int *v21; // [esp+38h] [ebp-8h]
  int v22; // [esp+3Ch] [ebp-4h]
  unsigned int vars0; // [esp+40h] [ebp+0h]
  void *retaddr; // [esp+44h] [ebp+4h]                        //这个函数终极恐怖,整个就是一个虚拟机

  vars0 = a3;
  v22 = a2;
  v21 = (int *)&vars0;
  v20 = &retaddr;
  v19 = a1;
  v15 = __readeflags();
  *(_DWORD *)(a13 + 4188) = retaddr;
  sub_472EAC(a13, a14, a12, a15, &v21, &v20, &v19);      //读取指令,并且翻译
  vars0 = v18;
  __writeeflags(v18);
  __writeeflags(v18);
  return v16(&vars0);  // 执行指令想,想不到吧
}
上面整个函数终极恐怖,他会把指令读出来然后进行翻译再执行
记录一下指令
00095032 add eax,0x7F   eax 34 ->b1                                                  ADD EAX, +7FH


         push 0x473A5E
		 retn
		 
00095034 xor edx,edx    edx -> 00000                                                 XOR EDX, EDX.
		 push 0x473A84
		 retn
	
00095035 cmp eax,edx    eax = B1  EDX = E0         c1 p1 a0 z0 s1 t0 d0 o0           CMP EAX, EDX             对比eax + 7h 比较 E0   eax = ‘a’   如果这里真确则retrun 到第一条指令
                                                                                                              对比eax + 7h 比较 B0   eax = ‘1’   如果这里真确则retrun 到第一条指令
         push 0x473A84                                                                                        对比eax + 7h 比较 B1   eax = ‘2’   如果这里真确则retrun 到第一条指令
		 retn                                                                           对比eax + 7h 比较 B2   eax = ‘3’  
                                                                                                             如果这里真确则retrun到第一条指令

00095035 nop
         nop
		 push 0x473A84                                                               JNZ +XX    是否回到第一条
		 retn
		 
00095046 nop                                                                         JMP +09H
         nop
		 push 0x473A84
		 retn
		 
		 LEA EAX, [EBP+FFFFFBE0H]
		 PUSH EAX
		 XOR ECX ECX 
		 CALL -000022D9H  call 00491DEC
整理一下意思就是
int __usercall sub_4734B0@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15)
{
  unsigned int v15; // et0
  int (__fastcall *v16)(unsigned int *); // ST10_4
  unsigned int v18; // [esp+10h] [ebp-30h]
  int v19; // [esp+30h] [ebp-10h]
  void **v20; // [esp+34h] [ebp-Ch]
  int *v21; // [esp+38h] [ebp-8h]
  int v22; // [esp+3Ch] [ebp-4h]
  unsigned int vars0; // [esp+40h] [ebp+0h]
  void *retaddr; // [esp+44h] [ebp+4h]                        //这个函数终极恐怖,整个就是一个虚拟机

  vars0 = a3;
  v22 = a2;
  v21 = (int *)&vars0;
  v20 = &retaddr;
  v19 = a1;
  v15 = __readeflags();
  *(_DWORD *)(a13 + 4188) = retaddr;
  sub_472EAC(a13, a14, a12, a15, &v21, &v20, &v19);      //读取指令,并且翻译
  vars0 = v18;
  __writeeflags(v18);
  __writeeflags(v18);
  return v16(&vars0);  // 执行指令想,想不到吧
}
上面整个函数终极恐怖,他会把指令读出来然后进行翻译再执行
记录一下指令

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 2428
活跃值: (159)
能力值: ( LV11,RANK:198 )
在线值:
发帖
回帖
粉丝
2
2019-3-27 09:33
0
游客
登录 | 注册 方可回帖
返回
//