首页
社区
课程
招聘
[原创] 看雪 2023 KCTF 年度赛 第三题 秘密计划
发表于: 2023-9-7 07:05 10238

[原创] 看雪 2023 KCTF 年度赛 第三题 秘密计划

2023-9-7 07:05
10238

为什么下载附件会被chrome认为危险拦截掉?!(目前三道题的附件都这样……)

Windows GUI程序,一个输入框,输入长度是32位。

IDA打开,41347个函数,看一眼字符串至少用了 soui4cryptoppunicorn等库,而且还是C++编写的,各种间接跳转虚函数调用等。虽然没有混淆,但本身程序的复杂性使得如何排除干扰找到真正的校验逻辑变成了一件并不轻松的事,特别是如何避免花费大量时间逆向结果是一个库函数。

这个程序编译C++时保留了RTTI信息,因此IDA把所有的虚表重命名了,方便了后面看伪代码对虚表赋值的地方猜测函数的作用。这些大部分都是CrytoPP的函数。

先学习soui4框架再从WinMain函数正向深入显然不适合短期解题。
注意到随着exe还有一个code.dat文件,程序中一定会打开它,然而直接搜索"code.dat"字符串找不到结果。换一个方向,在IDA中查找CreateFileW的交叉引用,只有十个左右的条目,顺次看下来,在sub_40DA90的伪代码中看到了L"code.dat",确认了这个函数出题人写的而不是库函数。

程序中大量使用了std::string,在IDA中定义出它的结构体(大小是6个DWORD共24字节,后两个DWORD是size和capacity,第一个DWORD是指向实际char *的指针,或者长度小于16时内联到结构体的前16字节),会让F5的伪代码观感提升不少,更重要的是局部变量的交叉引用能更准确。

粗略看一遍sub_40DA90,直观上是读入了code.dat文件,前8字节和后面的字节分别存成两个string,各自做了一些运算(跑了ClassInformer插件后,一些函数点进去后,虚表赋值的地方能看到CryptoPP的类名和函数名,至少有AES、HexDecode、CRC32等)。
合理猜测code.dat的前8字节是hexencode后的crc32,而后面的字节是加密过的不知道什么东西,中间的逻辑可能是解密然后crc校验,通过后又做了一些不知道什么的事。

虽然找到了sub_40DA90作为突破口,但是这里并没有获取输入的地方。
向上找,它的调用者sub_40CF80有很多SendMessageW;再上一级的调用者是sub_40CF60,是通过QueueUserWorkItem在其他线程中调用的sub_40CF80。而sub_40CF60本身在虚表中,通过静态分析很难再找到它的调用者了。

开始动态调试,但调试器附加后程序总是闪退,基本断定程序有反调试。简单试了x32dbg ScallyHide的几个默认选项发现无效,而一时间又很难静态分析从海量函数中找到反调试所在,初次陷入僵局。

在不断尝试中发现如果在sub_40CF60调用QueueUserWorkItem之前下断点,程序不会闪退。在此处查看调用栈,找到了它的调用者是sub_4061D0。这个函数有两处MessageBox分别是L"验证成功"验证失败,还有1146、1147、1148、1149、1150等几个常数的分支判断,所以这很可能是一个消息处理函数,几个常数对应几种不同的消息。

其中1149直接导向“验证失败”,到达“验证成功”则需要1147以及一个额外的判断。
回看sub_40CF80,里面有SendMessage 1147、1149、1150等,所以接下来期望找到1147的条件。

sub_40CF80的逻辑十分复杂,再加上调用了大量CrytoPP的密码学函数,要进一步分析还是依赖动态调试。而且,最难受的是,到现在仍然没有找到获取输入的地方。但无论如何,反调试问题仍然要先解决掉。

注意到程序在sub_40CF60调用QueueUserWorkItem之后才会闪退,所以可以把这里patch为直接调用sub_40CF80函数,不会影响逻辑,且调试器附加后程序不会闪退了。

依靠不断调试和猜,一点点梳理程序的逻辑。

sub_4061D0开始:(重名了一些函数)

消息为1146时参数是wchat_t *的输入字符串,然后调用了sub_406850,调试发现输出是转换为char *后的sha256值。继续调用sub_406D20,它的输出长度高达4096字节,在里面看到了RSA OAEP相关的虚表赋值,猜测这里做了一个RSA OAEP的加密。然后,依次调用了sub_40CF10sub_40CF60函数。

消息为1149时直接提示验证失败
消息为1147时还会额外检查 a1 + 652 不为0才会提示验证成功。但仔细观察,消息为 1150 时输入的offset=24的字节会覆盖这个值。

sub_40CF10 只是一个赋值

sub_40CF60 比较重要,通过 QueueUserWorkItem 调用了 sub_40CF80 函数:

第一步调用 sub_40D6A0 初始化了很多 uuid 常量。
然后循环遍历,作为参数调用 sub_40DA90 函数。如果成功返回了值,下一步用之前RSA OEAP加密的结果调用 sub_40E670,后者完成了解密,调试看到结果就是程序输入值的sha256。

继续跟踪数据流,如果要进入SendMessageW 1147,至少需要调用 sub_44DA50 的地方返回 0,然后还会根据 sub_44E1F0 的调用结果发送一个 1150 消息。回顾 sub_4061D0,1150 消息的offset=24的字节需要不为0才能在进入 1147 时进入“验证成功”的分支。

所以,决定验证通过的关键是 sub_44DA50sub_44E1F0 两个函数。上面贴的伪代码已经把它们标注出来了,分别是 unicorn 的 uc_emu_start 和 uc_mem_read。
而初始化unicorn内存时,0x4033地址用的是程序输入值的sha256;0x43000地址用的是 sub_40DA90 函数的返回值,动态调试可以发现它来自于解密的 code.dat,且它的 crc32 恰好是code.dat的前8字节hexdecode。

往上看,sub_44E640 uc_open 时用的是 UC_ARCH_ARM,所以 unicorn 0x43000 的值是 arm 指令。

实际上,最初完全没有想到过这些函数竟然属于unicorn,因为里面不像CryptoPP一样有虚表暴露了类名,而且很难找到可读的字符串。

(当然,从全局字符串可以知道程序用了unicorn,如果对它的api很敏感或许可以猜出这些函数;但是逆到这里早就没有印象了)

不过,我们可以借助其他工具的力量,例如 BinaryAI (之前在论坛也看到了宣传文:链接

文件的分析结果:链接

soui、cryptopp 都识别出来了(虽然版本都是错的),但是关键的 unicorn 却丢失了(IDA直接查字符串表就能看到unicorn,这个号称AI加持的平台却漏掉了)

(去平台首页-自定义比对-组件-比对内容,输入github链接,探测出平台对 unicorn 是有收录的,而soui只收录了 soui2soui3 却唯独没有soui4。之前另一篇宣传文章提到的“数万代码仓库、亿级函数特征”、“准确定位开源项目具体版本”看起来还有很大提升空间)

但是,交互式分析 页面还是带来了一些小惊喜。

例如 sub_44E640sub_44E1F0sub_44E460 等关键函数都被正确识别出来了:uc_openuc_mem_readuc_mem_write,连带它上下附近的函数都是 unicorn 相关的函数。(那么,平台首屏的组件列表为什么没展示呢)

(但如果筛选"匹配效果"为"命中",打上绿色Hit标记的函数反而都是soui2的一些奇奇怪怪的函数)
(而且,交互上不能按照十六进制地址搜索(浏览器地址栏的链接倒是能直接跳转到任意函数,但必须是十进制才行)、也不能按g或ctrl+g快速跳转到想要的函数,还是不太方便)

其他识别库函数的思路:

IDA的F.L.I.R.T函数签名:优点是十分精准,缺点是十分精准导致必须找到原始的.lib或.a等静态库才行。如果作者是从源代码自己编译的库,就完全无法发挥作用。

IDA Lumina:...

自己找到库的源代码编译一个二进制,然后用BinDiffdiaphora之类的工具找出匹配的二进制函数迁移符号:存在的问题题是自己编译库比较麻烦,还要确保库的版本和编译选项尽可能与程序接近才能保证最好的效果;而且,BinDiff和diaphora的识别率和准确率都不是很高。(这里再提一下BinaryAI,之前还针对这个场景发布过一个基于大模型的函数语义匹配功能(链接),官方评测效果非常好,不知道实际应用起来怎么样)

回到题目,确定是unicorn模拟执行code.dat解密出来的arm代码后,将其dump出来拖进IDA逆向分析:(基地址重定位到0x43000)

能看到雏形:MEMORY[0x143A8]的赋值就是后面SendMessageW 1150的参数的offset=24的位置,v1的0x4033地址对应程序输入的flag的sha256,而do-while循环很明显是对比两个字符串。

但是,从伪代码看似乎永远无法到达对MEMORY[0x143A8]赋值的地方,这是IDA的反编译错误。

从汇编看,v2来自于 0x436E4 的 POP {R2} 指令。随着do-while的每次循环,pop出来的值都会变化。所以,相当于flag的sha256循环与这里硬编码的所有常量比较,如果相等且这个常量是 "6749dae311865d64db83d5ae75bac3c9e36b3aa6f24caba655d9682f7f071023",就会成功对MEMORY[0x143A8]赋值。

总结下来,这段代码的作用就是:检查flag的sha256是"6749dae311865d64db83d5ae75bac3c9e36b3aa6f24caba655d9682f7f071023"

(这里需要一个双重分割线)

WTF ?? 出题人搞笑吧??逆了大半天,逻辑就一个sha256检查,咋可能逆的出来??难道又是爆哈希(第二题的阴影还未散去)?但这啥约束都没有,长度又是32,怎么可能爆的出来??

回想起放题前交流群说题目有氪金和不氪金的两种解法,难道氪金解法是sha256反查?马上打开cmd5,满怀期待的把sha256输进去,结果是“未查到”??那这氪金也氪不出来啊?难道真的如群友所说,氪金解法是直接向出题人买flag??

秉承对题目质量的信任(CTF逆向题出了个给sha256求原值,只在搞笑段子里见过),会不会是程序其他地方还有对flag的额外约束?

回想前面的逆向过程,可能的坑一个是反调试导致分析出的逻辑是错的,另一个是起始的1146消息是谁发的。

在IDA汇编窗口全局搜索47Ah(1146),果然找到了另一处:sub_406490

动态调试,这个函数开头是真实的获取输入框的内容,包括对长度32的检查;中间通过虚函数间接调用了sendmessage 1146,参数就是输入框的原始内容。

sub_406490的父级是sub_405AF0,已经明确的看到了L"btn_close"和L"check_va",所以发送消息这边应该没有更多逻辑了。

另一处1146的地方在sub_405C50

这里看起来是接收消息的主分发器所在(以及,它的上两级父级函数也是直接到了虚表中),前面有一个初始化函数 sub_405F10

CreateTimerQueueTimer初始化的 sub_407900 和 sub_4079D0 分别是 NtQueryInformationThread 和 NtQueryInformationProcess 调试器检测,如果检测到被调试就调用 ExitProcess 或 TerminateProcess 退出。
(但是,尝试patch这两处仍然会在调试时闪退,不知道哪里还有其他检测)

所以,看起来程序其他地方没有隐藏的逻辑了。所以题目真的能解吗?

无奈之下乱搞,把arm代码中的所有sha256都抄出来逐一往cmd5和google搜索塞,有了新的发现:

相邻的两条sha256,有的其中一条是简单整数的sha256,另一条是前面sha256的sha256。
自己尝试正向计算了一下补全表格,只剩两个无法搞出来,其中 6749dae311865d64db83d5ae75bac3c9e36b3aa6f24caba655d9682f7f071023 按照之前的分析是程序输入框的正确flag,那么按照上面表格的规律,它应该也是 ea96b41c1f9365c2c9e6342f5faaeab2a44471efe1e65a2356a974646d2588fd 的sha256,但实际计算下来却不对。

然后!随手把它往程序的输入框里粘贴,结果验证成功??再一看是被截断成了32位,所以正确的flag是 ea96b41c1f9365c2c9e6342f5faaeab2,计算了下它的sha256确实是 6749dae311865d64db83d5ae75bac3c9e36b3aa6f24caba655d9682f7f071023。

(writeup完。这里需要第二个双重分割线)

如果这真的是出题人的预设解法(希望不是如此,而是程序还有什么隐藏的校验逻辑我没有找到,等出题人公开解法,如果错怪了,在此先提前道歉然后删除此段),只能说今天长见识了,第一次见到出成这样的题也敢称为Reverse。
最后一步就全靠脑洞吗?程序的唯一关键路径只有一个不可逆的sha256,只靠分析程序运算逻辑无法逆推出flag;当然,或许可以解释为“隐藏线索”,然后这些sha256确实是刻意构造且存在规律的。这种脑洞题虽然不鼓励但也是能出的(当然选手如何评价是另一回事),但惯例上,这类题最多只能被归类为 Misc。那么,按照今年的规则,misc题目禁止参赛,应当如何处理呢?

另外,其实不太明白本次比赛规则为什么特别禁止了misc题目参赛。难道是因为去年秋季赛的无解misc么?
传统的四大分类(Pwn、Reverse、Crypto、Web),虽然没有成文的标准,但基本上是比较死板严格的(以Reverse为例,目标就是逆推出输入,那么程序中给的约束必须是充分且可逆的,而且应该以运算的方式在从输入flag到输出判定结果的数据流的关键路径上;而本题,唯一的线索是所谓的24个sha256找规律,除了实际参与判断的那个,其他都删掉或乱给,程序的校验逻辑仍然能通过,也就是说这些规律并不参与到判断flag正确性的运算中,而只是作为旁路的一个提示,因此完全从运算逻辑无法逆推),misc更多的作为一个补集,收容所有不进入四大类的题目。所以,高质量比赛经常出现一些思路创新但不便于按传统分类的题目放到misc中。
KCTF如果允许其他四类题目参赛但不允许misc,对题目的多样性是不友好的。合理猜测禁止的初衷是保证题目质量,避免脑洞/无解/作者自己不解(例如,随手写个加密算法套层vmp/重量级混淆当逆向题,但是出题人自己不公开自动化去混淆方法的情况,这种题适合在论坛中长期交流或悬赏,放到以技术交流为目的的比赛中是对攻击方的严重不公平)等情况出现,题目质量应该依靠验题来保证。
据了解,一些高质量国际赛的出题规范之一就是作者自己必须在“做题人”的视角下“真的”会解,因为比赛的目的是技术交流,而不是破解悬赏。例如,如果题目加了强混淆的,在公开预期解writeup时必须要给出自己的去混淆方法(自动化或工作量可承受的人工),而不是仅仅依靠自己知道混淆前的原算法,给一份逆推代码了事(这样搞等着被做题人喷吧),因为做题人在对抗混淆之前看不到原算法,所以出题人当站在做题人的视角上验题时,就不能一上来假设自己拥有原算法。

// sub_4061D0
int __userpurge handle_window_message@<eax>(
        int a1@<ecx>,
        int a2@<ebp>,
        int a3@<edi>,
        int a4,
        _OWORD *input_wchars,
        int a6)
{
  char *p_input_sha256; // edx
  void *s; // ecx
  char *v9; // edx
  char *v10; // edx
  int v11; // eax
  unsigned __int8 v12; // al
  char v13; // al
  int v15; // [esp-54h] [ebp-60h]
  unsigned __int8 v17; // [esp-45h] [ebp-51h]
  struct string input_sha256; // [esp-44h] [ebp-50h] BYREF
  struct string v19; // [esp-2Ch] [ebp-38h] BYREF
  int *v20; // [esp-10h] [ebp-1Ch]
  struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-Ch] [ebp-18h]
  void *v22; // [esp-8h] [ebp-14h]
  int v23; // [esp-4h] [ebp-10h]
  int v24[2]; // [esp+0h] [ebp-Ch] BYREF
  int v25; // [esp+8h] [ebp-4h] BYREF
  int retaddr; // [esp+Ch] [ebp+0h]
 
  v24[0] = a2;
  v24[1] = retaddr;
  v23 = -1;
  v22 = &loc_C0D4D5;
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
  v20 = &v25;
  if ( a4 != 1146 )
  {
    if ( a4 == 1147 )
    {
      if ( *(_BYTE *)(a1 + 652) )
        MessageBoxW(*(HWND *)(a1 + 28), L"验证成功!", L"提示", 0);
      else
        (*(void (__stdcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)a1 + 176))(a1, 1149, 0, 0);
      return 0;
    }
    if ( a4 == 1149 )
    {
      MessageBoxW(*(HWND *)(a1 + 28), L"验证失败!", L"提示", 0);
      return 0;
    }
    if ( a4 != 1148 )
    {
      if ( a4 == 1150 && input_wchars )
      {
        *(_OWORD *)(a1 + 628) = *input_wchars;
        *(_OWORD *)(a1 + 644) = input_wchars[1];
      }
      return 0;
    }
    v11 = *(_DWORD *)(a1 + 616);
    if ( !v11 )
      return 0;
    v12 = (*(int (__stdcall **)(int, int, int))(*(_DWORD *)(v11 + 4) + 300))(v11 + 4, v15, a3);// sub_A510A7
    v17 = v12;
    if ( v12 < 0x64u )
    {
      if ( v12 <= 0x50u )
      {
        if ( !byte_E43098 )
          byte_E43098 = 1;
        goto LABEL_37;
      }
      v13 = byte_E43098;
    }
    else
    {
      v13 = byte_E43098;
      if ( byte_E43098 == 1 )
      {
        v13 = 0;
        byte_E43098 = 0;
      }
    }
    if ( !v13 )
    {
      (*(void (__cdecl **)(int, _DWORD))(*(_DWORD *)(*(_DWORD *)(a1 + 616) + 4) + 296))(
        *(_DWORD *)(a1 + 616) + 4,
        (unsigned __int8)(v17 - 5));
      byte_E43098 = 0;
      return 0;
    }
LABEL_37:
    (*(void (__cdecl **)(int, _DWORD))(*(_DWORD *)(*(_DWORD *)(a1 + 616) + 4) + 296))(
      *(_DWORD *)(a1 + 616) + 4,
      (unsigned __int8)(v17 + 5));
    byte_E43098 = 1;
    return 0;
  }
  if ( input_wchars )
  {
    if ( !*(_WORD *)input_wchars )              // a5 is input wchat_t *
    {
      j_j__free(input_wchars);
      return 0;
    }
    sha256sum(&input_sha256, input_wchars, (int)v24, a6);// sub_406850 sha256
    v23 = 0;
    p_input_sha256 = (char *)&input_sha256;
    if ( input_sha256.capacity >= 0x10u )
      p_input_sha256 = input_sha256.s;
    sub_406D20(&v19, p_input_sha256);           // v20 may be rsa oaep encrypt result
    LOBYTE(v23) = 1;
    if ( v19.size )
    {
      s = &v19;
      if ( v19.capacity >= 0x10u )
        s = v19.s;
      (*(void (__thiscall **)(int, void *, int, _DWORD))(*(_DWORD *)(a1 + 680) + 8))(
        a1 + 680,
        s,
        v19.size,
        *(_DWORD *)(a1 + 28));                  // call sub_40CF10 simulation_function_8
      (*(void (__thiscall **)(int))(*(_DWORD *)(a1 + 680) + 12))(a1 + 680);// call sub_40CF60 simulation_function_c
    }
    else
    {
      (*(void (__stdcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)a1 + 176))(a1, 1149, 0, 0);
    }
    if ( v19.capacity >= 0x10u )
    {
      v9 = v19.s;
      if ( (unsigned int)(v19.capacity + 1) >= 0x1000 )
      {
        v9 = (char *)*((_DWORD *)v19.s - 1);
        if ( (unsigned int)(v19.s - v9 - 4) > 0x1F )
          goto LABEL_42;
      }
      free_(v9);
    }
    v19.size = 0;
    v19.capacity = 15;
    LOBYTE(v19.s) = 0;
    if ( input_sha256.capacity < 0x10u )
      return 0;
    v10 = input_sha256.s;
    if ( (unsigned int)(input_sha256.capacity + 1) < 0x1000
      || (v10 = (char *)*((_DWORD *)input_sha256.s - 1), (unsigned int)(input_sha256.s - v10 - 4) <= 0x1F) )
    {
      free_(v10);
      return 0;
    }
LABEL_42:
    _invalid_parameter_noinfo_noreturn();
  }
  return 0;
}
// sub_4061D0
int __userpurge handle_window_message@<eax>(
        int a1@<ecx>,
        int a2@<ebp>,
        int a3@<edi>,
        int a4,
        _OWORD *input_wchars,
        int a6)
{
  char *p_input_sha256; // edx
  void *s; // ecx
  char *v9; // edx
  char *v10; // edx
  int v11; // eax
  unsigned __int8 v12; // al
  char v13; // al
  int v15; // [esp-54h] [ebp-60h]
  unsigned __int8 v17; // [esp-45h] [ebp-51h]
  struct string input_sha256; // [esp-44h] [ebp-50h] BYREF
  struct string v19; // [esp-2Ch] [ebp-38h] BYREF
  int *v20; // [esp-10h] [ebp-1Ch]
  struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-Ch] [ebp-18h]
  void *v22; // [esp-8h] [ebp-14h]
  int v23; // [esp-4h] [ebp-10h]
  int v24[2]; // [esp+0h] [ebp-Ch] BYREF
  int v25; // [esp+8h] [ebp-4h] BYREF
  int retaddr; // [esp+Ch] [ebp+0h]
 
  v24[0] = a2;
  v24[1] = retaddr;
  v23 = -1;
  v22 = &loc_C0D4D5;
  ExceptionList = NtCurrentTeb()->NtTib.ExceptionList;
  v20 = &v25;
  if ( a4 != 1146 )
  {
    if ( a4 == 1147 )
    {
      if ( *(_BYTE *)(a1 + 652) )
        MessageBoxW(*(HWND *)(a1 + 28), L"验证成功!", L"提示", 0);
      else
        (*(void (__stdcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)a1 + 176))(a1, 1149, 0, 0);
      return 0;
    }
    if ( a4 == 1149 )
    {
      MessageBoxW(*(HWND *)(a1 + 28), L"验证失败!", L"提示", 0);
      return 0;
    }
    if ( a4 != 1148 )
    {
      if ( a4 == 1150 && input_wchars )
      {
        *(_OWORD *)(a1 + 628) = *input_wchars;
        *(_OWORD *)(a1 + 644) = input_wchars[1];
      }
      return 0;
    }
    v11 = *(_DWORD *)(a1 + 616);
    if ( !v11 )
      return 0;
    v12 = (*(int (__stdcall **)(int, int, int))(*(_DWORD *)(v11 + 4) + 300))(v11 + 4, v15, a3);// sub_A510A7
    v17 = v12;
    if ( v12 < 0x64u )
    {
      if ( v12 <= 0x50u )
      {
        if ( !byte_E43098 )
          byte_E43098 = 1;
        goto LABEL_37;
      }
      v13 = byte_E43098;
    }
    else
    {
      v13 = byte_E43098;
      if ( byte_E43098 == 1 )
      {
        v13 = 0;
        byte_E43098 = 0;
      }
    }
    if ( !v13 )
    {
      (*(void (__cdecl **)(int, _DWORD))(*(_DWORD *)(*(_DWORD *)(a1 + 616) + 4) + 296))(
        *(_DWORD *)(a1 + 616) + 4,
        (unsigned __int8)(v17 - 5));
      byte_E43098 = 0;
      return 0;
    }
LABEL_37:
    (*(void (__cdecl **)(int, _DWORD))(*(_DWORD *)(*(_DWORD *)(a1 + 616) + 4) + 296))(
      *(_DWORD *)(a1 + 616) + 4,
      (unsigned __int8)(v17 + 5));
    byte_E43098 = 1;
    return 0;
  }
  if ( input_wchars )
  {
    if ( !*(_WORD *)input_wchars )              // a5 is input wchat_t *
    {
      j_j__free(input_wchars);
      return 0;
    }
    sha256sum(&input_sha256, input_wchars, (int)v24, a6);// sub_406850 sha256
    v23 = 0;
    p_input_sha256 = (char *)&input_sha256;
    if ( input_sha256.capacity >= 0x10u )
      p_input_sha256 = input_sha256.s;
    sub_406D20(&v19, p_input_sha256);           // v20 may be rsa oaep encrypt result
    LOBYTE(v23) = 1;
    if ( v19.size )
    {
      s = &v19;
      if ( v19.capacity >= 0x10u )
        s = v19.s;
      (*(void (__thiscall **)(int, void *, int, _DWORD))(*(_DWORD *)(a1 + 680) + 8))(
        a1 + 680,
        s,
        v19.size,
        *(_DWORD *)(a1 + 28));                  // call sub_40CF10 simulation_function_8
      (*(void (__thiscall **)(int))(*(_DWORD *)(a1 + 680) + 12))(a1 + 680);// call sub_40CF60 simulation_function_c
    }
    else
    {
      (*(void (__stdcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)a1 + 176))(a1, 1149, 0, 0);
    }
    if ( v19.capacity >= 0x10u )
    {
      v9 = v19.s;
      if ( (unsigned int)(v19.capacity + 1) >= 0x1000 )
      {
        v9 = (char *)*((_DWORD *)v19.s - 1);
        if ( (unsigned int)(v19.s - v9 - 4) > 0x1F )
          goto LABEL_42;
      }
      free_(v9);
    }
    v19.size = 0;
    v19.capacity = 15;
    LOBYTE(v19.s) = 0;
    if ( input_sha256.capacity < 0x10u )
      return 0;
    v10 = input_sha256.s;
    if ( (unsigned int)(input_sha256.capacity + 1) < 0x1000
      || (v10 = (char *)*((_DWORD *)input_sha256.s - 1), (unsigned int)(input_sha256.s - v10 - 4) <= 0x1F) )
    {
      free_(v10);
      return 0;
    }
LABEL_42:
    _invalid_parameter_noinfo_noreturn();
  }
  return 0;
}
// sub_40CF80
// local variable allocation has failed, the output may be wrong!
DWORD __userpurge Function@<eax>(int a1@<ebx>, struct simulation_context *lpThreadParameter)
{
  struct string *begin; // esi
  bool v3; // cf
  _BYTE *s; // eax
  struct string *v5; // edi
  char *v6; // edx
  char *v7; // edx
  char *v8; // edx
  struct simulation_context *v9; // esi
  char *p_load_code_dat_return_string; // ecx
  unsigned __int8 *p_userinput_sha256; // edi
  int v12; // esi
  char *v13; // edx
  _BYTE *v14; // eax
  struct string *v15; // eax
  char *v16; // ecx
  unsigned int v17; // edi
  char *p_inputstr_sha256; // esi
  char *v19; // esi
  char *v20; // edx
  int v21; // esi
  void *v22; // eax
  LRESULT (__stdcall *sendmessagew)(HWND, UINT, WPARAM, LPARAM); // edi
  char *v24; // edx
  HWND hwnd; // eax
  char *v26; // edx
  unsigned __int64 v28; // [esp-4h] [ebp-1F4h]
  int v29; // [esp-4h] [ebp-1F4h]
  unsigned __int64 v30; // [esp+4h] [ebp-1ECh]
  struct string v31; // [esp+Ch] [ebp-1E4h] BYREF
  int v32; // [esp+24h] [ebp-1CCh]
  int v33; // [esp+28h] [ebp-1C8h]
  int v34; // [esp+2Ch] [ebp-1C4h]
  int v35; // [esp+30h] [ebp-1C0h]
  char v36; // [esp+34h] [ebp-1BCh]
  __int128 v37; // [esp+38h] [ebp-1B8h]
  int v38; // [esp+48h] [ebp-1A8h]
  int v39; // [esp+4Ch] [ebp-1A4h]
  char v40; // [esp+50h] [ebp-1A0h]
  int v41[18]; // [esp+54h] [ebp-19Ch] BYREF
  char v42; // [esp+9Ch] [ebp-154h]
  int *v43; // [esp+A8h] [ebp-148h]
  void (__cdecl *v44)(); // [esp+ACh] [ebp-144h]
  int (__cdecl *v45)(int, int); // [esp+B0h] [ebp-140h]
  char *p_load_code_dat_return_string_; // [esp+B4h] [ebp-13Ch]
  int size; // [esp+B8h] [ebp-138h]
  unsigned __int8 *p_userinput_sha256_; // [esp+BCh] [ebp-134h]
  int v49; // [esp+C0h] [ebp-130h]
  int v50; // [esp+C4h] [ebp-12Ch] BYREF
  int v51; // [esp+C8h] [ebp-128h]
  LPVOID lpAddress; // [esp+CCh] [ebp-124h]
  struct simulation_context *v53; // [esp+D0h] [ebp-120h]
  char iftocheck; // [esp+D7h] [ebp-119h] BYREF
  void *Block; // [esp+D8h] [ebp-118h] BYREF
  int v56[39]; // [esp+DCh] [ebp-114h] BYREF
  struct string userinput_sha256; // [esp+178h] [ebp-78h] BYREF
  struct string inputstr_sha256; // [esp+190h] [ebp-60h] BYREF
  struct string load_code_dat_return_string; // [esp+1A8h] [ebp-48h] BYREF
  WPARAM wParam[2]; // [esp+1C0h] [ebp-30h] OVERLAPPED BYREF
  struct string tmp; // [esp+1C8h] [ebp-28h] BYREF
  int v62; // [esp+1ECh] [ebp-4h]
 
  v53 = lpThreadParameter;
  if ( !lpThreadParameter )
    return 0;
  (*(void (__thiscall **)(struct simulation_context *))lpThreadParameter->vtbl)(lpThreadParameter);// sub_40D6A0 simulation_function_0
  memset(&load_code_dat_return_string, 0, 20);
  load_code_dat_return_string.capacity = 15;
  LOBYTE(load_code_dat_return_string.s) = 0;
  v62 = 0;
  begin = lpThreadParameter->uuids.begin;
  lpAddress = v53->uuids.end;
  if ( begin != lpAddress )
  {
    while ( 1 )
    {
      v3 = begin->capacity < 0x10u;
      s = begin;
      iftocheck = 0;
      if ( !v3 )
        s = begin->s;
      v5 = (struct string *)load_code_dat(&tmp, &iftocheck, s);  // sub_40DA90
      if ( &load_code_dat_return_string != v5 )
      {
        if ( load_code_dat_return_string.capacity >= 0x10u )
        {
          v6 = load_code_dat_return_string.s;
          if ( (unsigned int)(load_code_dat_return_string.capacity + 1) >= 0x1000 )
          {
            v6 = (char *)*((_DWORD *)load_code_dat_return_string.s - 1);
            if ( (unsigned int)(load_code_dat_return_string.s - v6 - 4) > 0x1F )
              goto LABEL_76;
          }
          free_(v6);
        }
        load_code_dat_return_string.size = 0;
        load_code_dat_return_string.capacity = 15;
        LOBYTE(load_code_dat_return_string.s) = 0;
        load_code_dat_return_string = *v5;
        v5->size = 0;
        v5->capacity = 15;
        LOBYTE(v5->s) = 0;
      }
      if ( tmp.capacity >= 0x10u )
      {
        v7 = tmp.s;
        if ( (unsigned int)(tmp.capacity + 1) >= 4096 )
        {
          v7 = (char *)*((_DWORD *)tmp.s - 1);
          if ( (unsigned int)(tmp.s - v7 - 4) > 31 )
            goto LABEL_76;
        }
        free_(v7);
      }
      if ( iftocheck )
        break;
      if ( ++begin == lpAddress )
        goto LABEL_17;
    }
    if ( load_code_dat_return_string.size )
    {
      v9 = v53;
      (*(void (__thiscall **)(struct simulation_context *, struct string *))(v53->vtbl + 4))(v53, &userinput_sha256);// sub_40E670 simulation_function_4
                                                // may be rsa decrypt
      LOBYTE(v62) = 1;
      if ( !userinput_sha256.size )             // the output v57 is sha256 of user input
      {
        SendMessageW((HWND)v53->hwnd, 1149u, 0, 0);
LABEL_68:
        if ( userinput_sha256.capacity >= 0x10u )
        {
          v26 = userinput_sha256.s;
          if ( (unsigned int)(userinput_sha256.capacity + 1) >= 0x1000 )
          {
            v26 = (char *)*((_DWORD *)userinput_sha256.s - 1);
            if ( (unsigned int)(userinput_sha256.s - v26 - 4) > 0x1F )
              goto LABEL_75;
          }
          free_(v26);
        }
        userinput_sha256.size = 0;
        userinput_sha256.capacity = 15;
        LOBYTE(userinput_sha256.s) = 0;
        goto LABEL_18;
      }
      p_load_code_dat_return_string = (char *)&load_code_dat_return_string;
      p_userinput_sha256 = (unsigned __int8 *)&userinput_sha256;
      if ( load_code_dat_return_string.capacity >= 0x10u )
        p_load_code_dat_return_string = load_code_dat_return_string.s;
      p_load_code_dat_return_string_ = p_load_code_dat_return_string;
      if ( userinput_sha256.capacity >= 0x10u )
        p_userinput_sha256 = (unsigned __int8 *)userinput_sha256.s;
      p_userinput_sha256_ = p_userinput_sha256;
      size = load_code_dat_return_string.size;
      iftocheck = 0;
      if ( p_userinput_sha256 && p_load_code_dat_return_string && load_code_dat_return_string.size )
      {
        lpAddress = VirtualAlloc(0, (SIZE_T)&loc_A00000, 0x3000u, 0x40u);
        if ( lpAddress )
        {
          Block = 0;
          if ( uc_open(1, 0, &Block) )          // sub_44E640  UC_ARCH_ARM = 1
          {
            sendmessagew = SendMessageW;
          }
          else
          {
            LODWORD(v28) = 17;
            uc_ctl((int *)Block, 0x44000007u, v28, v30);
            memset(&inputstr_sha256, 0, 20);
            inputstr_sha256.capacity = 15;
            LOBYTE(inputstr_sha256.s) = 0;
            v12 = 0;
            v51 = 0;
            while ( 1 )
            {
              memset(v56, 0, sizeof(v56));
              v50 = p_userinput_sha256[v12];
              memset(&v31, 0, sizeof(v31));
              v32 = 0;
              v33 = 0;
              v37 = 0i64;
              v34 = 0;
              v35 = 0;
              v36 = 0;
              v38 = 0;
              v39 = 15;
              LOBYTE(v37) = 0;
              LOBYTE(v62) = 5;
              v40 = -1;
              sub_412030(v41, v29);
              v42 = 0;
              LOBYTE(v62) = 7;
              memset(&tmp, 0, sizeof(tmp));
              std_string_assign__(&tmp, "%02x", 4u);
              LOBYTE(v62) = 8;
              sub_412190(&v31, &tmp);
              LOBYTE(v62) = 7;
              if ( tmp.capacity >= 0x10u )
              {
                v13 = tmp.s;
                if ( (unsigned int)(tmp.capacity + 1) >= 0x1000 )
                {
                  v13 = (char *)*((_DWORD *)tmp.s - 1);
                  if ( (unsigned int)(tmp.s - v13 - 4) > 0x1F )
                    goto LABEL_76;
                }
                free_(v13);
              }
              tmp.size = 0;
              tmp.capacity = 15;
              LOBYTE(tmp.s) = 0;
              LOBYTE(v62) = 9;
              v43 = &v50;
              v44 = nullsub_1;
              v45 = sub_414C90;
              v14 = sub_414130(&v31);
              sub_410F70(v14);
              LOBYTE(v62) = 11;
              sub_40F4A0(&v31);
              v15 = sub_4111C0(v56, &tmp);      // hexencode input_sha256, result is only 2 bytes
              LOBYTE(v62) = 12;
              v16 = (char *)v15;
              if ( v15->capacity >= 0x10u )
                v16 = v15->s;
              v17 = v15->size;
              if ( v17 > inputstr_sha256.capacity - inputstr_sha256.size )
              {
                LOBYTE(v49) = 0;
                sub_40A700((void **)&inputstr_sha256.s, v17, v49, v16, v17);// /
              }
              else
              {
                p_inputstr_sha256 = (char *)&inputstr_sha256;
                if ( inputstr_sha256.capacity >= 0x10u )
                  p_inputstr_sha256 = inputstr_sha256.s;
                v19 = &p_inputstr_sha256[inputstr_sha256.size];
                inputstr_sha256.size += v17;
                memmove(v19, v16, v17);
                v19[v17] = 0;
                v12 = v51;
              }
              LOBYTE(v62) = 11;
              if ( tmp.capacity >= 0x10u )
              {
                v20 = tmp.s;
                if ( (unsigned int)(tmp.capacity + 1) >= 0x1000 )
                {
                  v20 = (char *)*((_DWORD *)tmp.s - 1);
                  if ( (unsigned int)(tmp.s - v20 - 4) > 0x1F )
                    goto LABEL_76;
                }
                free_(v20);
              }
              LOBYTE(v62) = 2;
              sub_40F4A0(v56);
              v51 = ++v12;
              if ( v12 >= 32 )
                break;
              p_userinput_sha256 = p_userinput_sha256_;
            }
            uc_mem_map((int)Block, 0, 0, 0xA00000, 7, (int)lpAddress);
            v21 = size;
            uc_mem_write((int)Block, 0x43000i64, (int)p_load_code_dat_return_string_, size); // sub_44E460
            v22 = &inputstr_sha256;
            if ( inputstr_sha256.capacity >= 0x10u )
              v22 = inputstr_sha256.s;
            uc_mem_write((int)Block, 0x4033i64, (int)v22, inputstr_sha256.size); // sub_44E460
            if ( uc_emu_start(a1, v17, (int)Block, 0x43000, 0, v21 + 0x43000, 0, 0i64, 0) ) // sub_44DA50
            {
              v9 = v53;
              sendmessagew = SendMessageW;
            }
            else
            {
              *(_OWORD *)wParam = 0i64;
              *(_OWORD *)&tmp.field_8 = 0i64;
              uc_mem_read((int)Block, 0x14390u, 0, (int)wParam); // sub_44E1F0
              v9 = v53;
              sendmessagew = SendMessageW;
              iftocheck = 1;
              SendMessageW((HWND)v53->hwnd, 1150u, (WPARAM)wParam, 0);// first send, need offset 24 of wParam is 1
            }
            sub_44E300((int)Block, 0i64, (unsigned int)&loc_A00000);
            sub_44D470((char *)Block);
            if ( inputstr_sha256.capacity >= 0x10u )
            {
              v24 = inputstr_sha256.s;
              if ( (unsigned int)(inputstr_sha256.capacity + 1) >= 0x1000 )
              {
                v24 = (char *)*((_DWORD *)inputstr_sha256.s - 1);
                if ( (unsigned int)(inputstr_sha256.s - v24 - 4) > 0x1F )
LABEL_76:
                  _invalid_parameter_noinfo_noreturn();
              }
              free_(v24);
            }
          }
          VirtualFree(lpAddress, 0, 0x8000u);
        }
        else
        {
          sendmessagew = SendMessageW;
        }
        hwnd = (HWND)v9->hwnd;
        if ( iftocheck )
        {
          sendmessagew(hwnd, 1147u, 0, 0);      // final check
          goto LABEL_68;
        }
      }
      else
      {
        hwnd = (HWND)v53->hwnd;
        sendmessagew = SendMessageW;
      }
      sendmessagew(hwnd, 1149u, 0, 0);
      goto LABEL_68;
    }
  }
LABEL_17:
  SendMessageW((HWND)v53->hwnd, 1149u, 0, 0);
LABEL_18:
  if ( load_code_dat_return_string.capacity >= 0x10u )
  {
    v8 = load_code_dat_return_string.s;
    if ( (unsigned int)(load_code_dat_return_string.capacity + 1) < 0x1000
      || (v8 = (char *)*((_DWORD *)load_code_dat_return_string.s - 1),
          (unsigned int)(load_code_dat_return_string.s - v8 - 4) <= 0x1F) )
    {
      free_(v8);
      return 0;
    }
LABEL_75:
    _invalid_parameter_noinfo_noreturn();
  }
  return 0;
}
// sub_40CF80
// local variable allocation has failed, the output may be wrong!
DWORD __userpurge Function@<eax>(int a1@<ebx>, struct simulation_context *lpThreadParameter)
{
  struct string *begin; // esi
  bool v3; // cf
  _BYTE *s; // eax
  struct string *v5; // edi
  char *v6; // edx
  char *v7; // edx
  char *v8; // edx
  struct simulation_context *v9; // esi
  char *p_load_code_dat_return_string; // ecx
  unsigned __int8 *p_userinput_sha256; // edi
  int v12; // esi
  char *v13; // edx
  _BYTE *v14; // eax
  struct string *v15; // eax
  char *v16; // ecx
  unsigned int v17; // edi
  char *p_inputstr_sha256; // esi
  char *v19; // esi
  char *v20; // edx
  int v21; // esi
  void *v22; // eax
  LRESULT (__stdcall *sendmessagew)(HWND, UINT, WPARAM, LPARAM); // edi
  char *v24; // edx
  HWND hwnd; // eax
  char *v26; // edx
  unsigned __int64 v28; // [esp-4h] [ebp-1F4h]
  int v29; // [esp-4h] [ebp-1F4h]
  unsigned __int64 v30; // [esp+4h] [ebp-1ECh]
  struct string v31; // [esp+Ch] [ebp-1E4h] BYREF
  int v32; // [esp+24h] [ebp-1CCh]
  int v33; // [esp+28h] [ebp-1C8h]
  int v34; // [esp+2Ch] [ebp-1C4h]
  int v35; // [esp+30h] [ebp-1C0h]
  char v36; // [esp+34h] [ebp-1BCh]
  __int128 v37; // [esp+38h] [ebp-1B8h]
  int v38; // [esp+48h] [ebp-1A8h]
  int v39; // [esp+4Ch] [ebp-1A4h]
  char v40; // [esp+50h] [ebp-1A0h]
  int v41[18]; // [esp+54h] [ebp-19Ch] BYREF
  char v42; // [esp+9Ch] [ebp-154h]
  int *v43; // [esp+A8h] [ebp-148h]
  void (__cdecl *v44)(); // [esp+ACh] [ebp-144h]
  int (__cdecl *v45)(int, int); // [esp+B0h] [ebp-140h]
  char *p_load_code_dat_return_string_; // [esp+B4h] [ebp-13Ch]
  int size; // [esp+B8h] [ebp-138h]
  unsigned __int8 *p_userinput_sha256_; // [esp+BCh] [ebp-134h]
  int v49; // [esp+C0h] [ebp-130h]
  int v50; // [esp+C4h] [ebp-12Ch] BYREF
  int v51; // [esp+C8h] [ebp-128h]
  LPVOID lpAddress; // [esp+CCh] [ebp-124h]
  struct simulation_context *v53; // [esp+D0h] [ebp-120h]
  char iftocheck; // [esp+D7h] [ebp-119h] BYREF
  void *Block; // [esp+D8h] [ebp-118h] BYREF
  int v56[39]; // [esp+DCh] [ebp-114h] BYREF
  struct string userinput_sha256; // [esp+178h] [ebp-78h] BYREF
  struct string inputstr_sha256; // [esp+190h] [ebp-60h] BYREF
  struct string load_code_dat_return_string; // [esp+1A8h] [ebp-48h] BYREF
  WPARAM wParam[2]; // [esp+1C0h] [ebp-30h] OVERLAPPED BYREF
  struct string tmp; // [esp+1C8h] [ebp-28h] BYREF
  int v62; // [esp+1ECh] [ebp-4h]
 
  v53 = lpThreadParameter;
  if ( !lpThreadParameter )
    return 0;
  (*(void (__thiscall **)(struct simulation_context *))lpThreadParameter->vtbl)(lpThreadParameter);// sub_40D6A0 simulation_function_0
  memset(&load_code_dat_return_string, 0, 20);
  load_code_dat_return_string.capacity = 15;
  LOBYTE(load_code_dat_return_string.s) = 0;
  v62 = 0;
  begin = lpThreadParameter->uuids.begin;
  lpAddress = v53->uuids.end;
  if ( begin != lpAddress )
  {
    while ( 1 )
    {
      v3 = begin->capacity < 0x10u;
      s = begin;
      iftocheck = 0;
      if ( !v3 )
        s = begin->s;
      v5 = (struct string *)load_code_dat(&tmp, &iftocheck, s);  // sub_40DA90
      if ( &load_code_dat_return_string != v5 )
      {
        if ( load_code_dat_return_string.capacity >= 0x10u )
        {
          v6 = load_code_dat_return_string.s;
          if ( (unsigned int)(load_code_dat_return_string.capacity + 1) >= 0x1000 )
          {
            v6 = (char *)*((_DWORD *)load_code_dat_return_string.s - 1);
            if ( (unsigned int)(load_code_dat_return_string.s - v6 - 4) > 0x1F )
              goto LABEL_76;
          }
          free_(v6);
        }
        load_code_dat_return_string.size = 0;
        load_code_dat_return_string.capacity = 15;
        LOBYTE(load_code_dat_return_string.s) = 0;
        load_code_dat_return_string = *v5;
        v5->size = 0;
        v5->capacity = 15;
        LOBYTE(v5->s) = 0;
      }
      if ( tmp.capacity >= 0x10u )
      {
        v7 = tmp.s;
        if ( (unsigned int)(tmp.capacity + 1) >= 4096 )
        {
          v7 = (char *)*((_DWORD *)tmp.s - 1);
          if ( (unsigned int)(tmp.s - v7 - 4) > 31 )
            goto LABEL_76;
        }
        free_(v7);
      }
      if ( iftocheck )
        break;
      if ( ++begin == lpAddress )
        goto LABEL_17;
    }
    if ( load_code_dat_return_string.size )
    {
      v9 = v53;
      (*(void (__thiscall **)(struct simulation_context *, struct string *))(v53->vtbl + 4))(v53, &userinput_sha256);// sub_40E670 simulation_function_4
                                                // may be rsa decrypt
      LOBYTE(v62) = 1;
      if ( !userinput_sha256.size )             // the output v57 is sha256 of user input
      {
        SendMessageW((HWND)v53->hwnd, 1149u, 0, 0);
LABEL_68:
        if ( userinput_sha256.capacity >= 0x10u )
        {
          v26 = userinput_sha256.s;
          if ( (unsigned int)(userinput_sha256.capacity + 1) >= 0x1000 )
          {
            v26 = (char *)*((_DWORD *)userinput_sha256.s - 1);
            if ( (unsigned int)(userinput_sha256.s - v26 - 4) > 0x1F )
              goto LABEL_75;
          }
          free_(v26);
        }
        userinput_sha256.size = 0;
        userinput_sha256.capacity = 15;
        LOBYTE(userinput_sha256.s) = 0;
        goto LABEL_18;
      }
      p_load_code_dat_return_string = (char *)&load_code_dat_return_string;
      p_userinput_sha256 = (unsigned __int8 *)&userinput_sha256;
      if ( load_code_dat_return_string.capacity >= 0x10u )
        p_load_code_dat_return_string = load_code_dat_return_string.s;
      p_load_code_dat_return_string_ = p_load_code_dat_return_string;
      if ( userinput_sha256.capacity >= 0x10u )
        p_userinput_sha256 = (unsigned __int8 *)userinput_sha256.s;
      p_userinput_sha256_ = p_userinput_sha256;
      size = load_code_dat_return_string.size;
      iftocheck = 0;
      if ( p_userinput_sha256 && p_load_code_dat_return_string && load_code_dat_return_string.size )
      {
        lpAddress = VirtualAlloc(0, (SIZE_T)&loc_A00000, 0x3000u, 0x40u);
        if ( lpAddress )
        {
          Block = 0;
          if ( uc_open(1, 0, &Block) )          // sub_44E640  UC_ARCH_ARM = 1
          {
            sendmessagew = SendMessageW;
          }
          else
          {
            LODWORD(v28) = 17;
            uc_ctl((int *)Block, 0x44000007u, v28, v30);
            memset(&inputstr_sha256, 0, 20);
            inputstr_sha256.capacity = 15;
            LOBYTE(inputstr_sha256.s) = 0;
            v12 = 0;
            v51 = 0;
            while ( 1 )
            {
              memset(v56, 0, sizeof(v56));
              v50 = p_userinput_sha256[v12];
              memset(&v31, 0, sizeof(v31));
              v32 = 0;
              v33 = 0;
              v37 = 0i64;
              v34 = 0;
              v35 = 0;
              v36 = 0;
              v38 = 0;
              v39 = 15;
              LOBYTE(v37) = 0;
              LOBYTE(v62) = 5;
              v40 = -1;
              sub_412030(v41, v29);
              v42 = 0;
              LOBYTE(v62) = 7;
              memset(&tmp, 0, sizeof(tmp));
              std_string_assign__(&tmp, "%02x", 4u);
              LOBYTE(v62) = 8;
              sub_412190(&v31, &tmp);
              LOBYTE(v62) = 7;
              if ( tmp.capacity >= 0x10u )
              {
                v13 = tmp.s;
                if ( (unsigned int)(tmp.capacity + 1) >= 0x1000 )
                {
                  v13 = (char *)*((_DWORD *)tmp.s - 1);
                  if ( (unsigned int)(tmp.s - v13 - 4) > 0x1F )
                    goto LABEL_76;
                }
                free_(v13);
              }
              tmp.size = 0;
              tmp.capacity = 15;
              LOBYTE(tmp.s) = 0;
              LOBYTE(v62) = 9;
              v43 = &v50;
              v44 = nullsub_1;
              v45 = sub_414C90;
              v14 = sub_414130(&v31);
              sub_410F70(v14);
              LOBYTE(v62) = 11;
              sub_40F4A0(&v31);
              v15 = sub_4111C0(v56, &tmp);      // hexencode input_sha256, result is only 2 bytes
              LOBYTE(v62) = 12;
              v16 = (char *)v15;
              if ( v15->capacity >= 0x10u )
                v16 = v15->s;
              v17 = v15->size;
              if ( v17 > inputstr_sha256.capacity - inputstr_sha256.size )
              {
                LOBYTE(v49) = 0;
                sub_40A700((void **)&inputstr_sha256.s, v17, v49, v16, v17);// /
              }
              else
              {
                p_inputstr_sha256 = (char *)&inputstr_sha256;
                if ( inputstr_sha256.capacity >= 0x10u )
                  p_inputstr_sha256 = inputstr_sha256.s;
                v19 = &p_inputstr_sha256[inputstr_sha256.size];
                inputstr_sha256.size += v17;
                memmove(v19, v16, v17);
                v19[v17] = 0;
                v12 = v51;
              }
              LOBYTE(v62) = 11;
              if ( tmp.capacity >= 0x10u )
              {
                v20 = tmp.s;
                if ( (unsigned int)(tmp.capacity + 1) >= 0x1000 )
                {
                  v20 = (char *)*((_DWORD *)tmp.s - 1);
                  if ( (unsigned int)(tmp.s - v20 - 4) > 0x1F )
                    goto LABEL_76;
                }
                free_(v20);
              }
              LOBYTE(v62) = 2;
              sub_40F4A0(v56);
              v51 = ++v12;
              if ( v12 >= 32 )
                break;
              p_userinput_sha256 = p_userinput_sha256_;
            }
            uc_mem_map((int)Block, 0, 0, 0xA00000, 7, (int)lpAddress);
            v21 = size;
            uc_mem_write((int)Block, 0x43000i64, (int)p_load_code_dat_return_string_, size); // sub_44E460
            v22 = &inputstr_sha256;
            if ( inputstr_sha256.capacity >= 0x10u )
              v22 = inputstr_sha256.s;
            uc_mem_write((int)Block, 0x4033i64, (int)v22, inputstr_sha256.size); // sub_44E460
            if ( uc_emu_start(a1, v17, (int)Block, 0x43000, 0, v21 + 0x43000, 0, 0i64, 0) ) // sub_44DA50
            {
              v9 = v53;
              sendmessagew = SendMessageW;
            }
            else
            {
              *(_OWORD *)wParam = 0i64;
              *(_OWORD *)&tmp.field_8 = 0i64;
              uc_mem_read((int)Block, 0x14390u, 0, (int)wParam); // sub_44E1F0
              v9 = v53;
              sendmessagew = SendMessageW;
              iftocheck = 1;
              SendMessageW((HWND)v53->hwnd, 1150u, (WPARAM)wParam, 0);// first send, need offset 24 of wParam is 1
            }
            sub_44E300((int)Block, 0i64, (unsigned int)&loc_A00000);
            sub_44D470((char *)Block);
            if ( inputstr_sha256.capacity >= 0x10u )
            {
              v24 = inputstr_sha256.s;
              if ( (unsigned int)(inputstr_sha256.capacity + 1) >= 0x1000 )
              {

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

收藏
免费 8
支持
分享
最新回复 (2)
雪    币: 6533
活跃值: (4331)
能力值: ( LV10,RANK:163 )
在线值:
发帖
回帖
粉丝
2
不好意思,对不起!  这题的本意是想让大家体验分析过程的乐趣,结果不重要。。。
原本arm代码里面有sha256明文加回去的代码rsa解密等一系列代码,但是怕代码太长太多影响分析时间,所以直接去掉给出了明文。
2023-9-7 13:41
0
雪    币: 3070
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2023-9-8 09:36
1
游客
登录 | 注册 方可回帖
返回
//