Dynamic Analysis with Frida
The Limits of Static Analysis
In a previous post, we explored how to defeat native anti-tamper checks by statically analyzing a library in Ghidra and then patching the binary.
Static analysis is a powerful first step, but it has one fundamental weakness: you are reasoning about what the code does, not what it actually does at runtime.
Highly hardened applications deliberately make this harder. They may:
- Pack or encrypt their native libraries: the
.sofile on disk is not the one that runs. - Load libraries late: the library you care about doesn’t exist in memory at startup.
- Layer defenses: bypassing one check exposes another that you couldn’t even see before.
When static approaches stall, we need to shift gears and move to dynamic analysis — intercepting the application as it runs, hooking functions in memory, and manipulating behavior on the fly.
This is precisely what Frida is built for.
The Target: OWASP UnCrackable Level 3
The target for this walkthrough is the OWASP UnCrackable Android App Level 3 — a deliberately hardened crackme designed to challenge reverse engineers.
The goal is simple on the surface: enter the correct secret string into the app’s input field and press Verify.
Getting there is anything but simple. The app employs a full stack of defenses:
- Java-layer anti-tamper: root detection (
RootDetection.checkRoot1/2/3), a debuggability check (IntegrityCheck.isDebuggable), and a library integrity verifier (MainActivity.verifyLibs). - Native-layer Frida detection:
libfoo.soactively scans for signs of instrumentation and, if it finds any, sendsSIGKILLto the process via a forked watchdog. /proc/self/mapsinspection: before the watchdog even starts, the library reads its own memory map looking for Frida’s agent.sofile, which appears as a mapped region with a recognisable name.- Secret obfuscation: the target string is stored XOR-encrypted and is only decrypted in memory at the moment it is needed — it is never present in plaintext on disk.
We will defeat all of these layers with a single Frida script.
Prerequisites: Extracting and Analysing the Native Library
Before we can write a single line of Frida JavaScript, we need to understand what we are hooking. Dynamic instrumentation and static analysis are not competing approaches — the best Frida scripts are written with a disassembler open in the other window.
The APK ships libfoo.so compiled for four ABIs: arm64-v8a, armeabi-v7a, x86, and x86_64. For this walkthrough we’ll target the x86_64 build.
Why
x86_64and notarm64-v8a?
Thex86_64binary runs natively on an Android emulator (AVD) without the overhead of instruction translation. The offsets we find in this library are the ones we’ll use directly in the script — no cross-architecture guesswork.
Step 1 — Extract the Library from the APK
An APK is just a ZIP archive. Open it in jadx-gui (or simply unzip it on the command line) and navigate to Resources → lib → x86_64. You’ll find libfoo.so sitting there:

Right-click the file in jadx and choose Export (or drag it out of the archive if using a file manager). Place it somewhere convenient — we’ll load it into Ghidra next.
Step 2 — Load into Ghidra
Open Ghidra, create a new project, and import the libfoo.so file (File → Import File). Ghidra will auto-detect it as an ELF shared library for the x86-64 ISA.

When the import dialog finishes, double-click the file to open it in the CodeBrowser. Click Yes when asked to run auto-analysis — this populates the symbol tree, resolves imports, and gives Ghidra’s decompiler enough context to produce readable C.


The three offsets that matter for our script are found in the Symbol Tree and the Listing view:
| Symbol / Offset | Address in Ghidra | What it does |
|---|---|---|
FUN_001037c0 | 0x001037c0 → offset 0x37c0 | Frida detection routine |
FUN_00103910 | 0x00103910 → offset 0x3910 | Watchdog fork call |
FUN_001012c0 | 0x001012c0 → offset 0x12c0 | Secret XOR decryption |
goodbye | exported symbol | Kill-switch that crashes the app |
With those offsets noted, load the same app onto your emulator and attach Frida — the runtime addresses will be module.base + offset for each one, since ASLR only shifts the base.
A Bird’s-Eye View of the Script
Before going layer by layer, it’s useful to understand the overall flow of the script. All the individual pieces feed into a single chain of callbacks:
blindMaps()
└─> hookNativeLib('libfoo.so', bypassNDKAntiTamper)
└─> bypassNDKAntiTamper('libfoo.so')
└─> disableJavaAntiTamper()
└─> exploit('libfoo.so')
Each step in the chain unlocks the next. We have to neutralize the lower-level (native) defenses first, before the Java layer can be safely patched, before we can finally intercept the secret.
The entry point is blindMaps(), called at the very end of the script. Let’s work through each stage.
Stage 1: Blinding the /proc/self/maps Check
The very first thing we do is attack the anti-instrumentation check at its root.
void FUN_001037c0(void)
{
FILE *__stream;
char *pcVar1;
char acStack_238 [520];
__stream = fopen("/proc/self/maps","r");
if (__stream == (FILE *)0x0) {
LAB_0010386c:
pcVar1 = "Error opening /proc/self/maps! Terminating...";
}
else {
do {
while (pcVar1 = fgets(acStack_238,0x200,__stream), pcVar1 == (char *)0x0) {
fclose(__stream);
usleep(500);
__stream = fopen("/proc/self/maps","r");
if (__stream == (FILE *)0x0) goto LAB_0010386c;
}
pcVar1 = strstr(acStack_238,"frida");
} while ((pcVar1 == (char *)0x0) &&
(pcVar1 = strstr(acStack_238,"xposed"), pcVar1 == (char *)0x0));
pcVar1 = "Tampering detected! Terminating...";
}
__android_log_print(2,"UnCrackable3",pcVar1);
/* WARNING: Subroutine does not return */
goodbye();
}
Where goodbye function is simply:
/* WARNING: Unknown calling convention -- yet parameter storage is locked */
/* goodbye() */
void goodbye(void)
{
raise(6);
/* WARNING: Subroutine does not return */
_exit(0);
}
/proc/self/maps is a Linux pseudo-file that lists every memory region mapped into the current process — including its address, permissions, and the name of the file it’s backed by. It’s a goldmine for integrity checkers: a native library can open this file, scan it for strings like frida-agent, and if found, know that Frida is attached and kill the process.
Our counter-measure is a full replacement of fopen at the native level.
fopen(3) Library Functions Manual fopen(3)
NAME
fopen, fdopen, freopen - stream open functions
LIBRARY
Standard C library (libc, -lc)
SYNOPSIS
#include <stdio.h>
FILE *fopen(const char *restrict path, const char *restrict mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *restrict path, const char *restrict mode,
FILE *restrict stream);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
fdopen():
_POSIX_C_SOURCE
.....
.....
.....
RETURN VALUE
Upon successful completion fopen(), fdopen(), and freopen() return a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error.
....
Interceptor.replace is more powerful than Interceptor.attach. Instead of hooking before/after a function, it completely swaps out the function pointer with our own NativeCallback. Every call to fopen anywhere in the process now goes through our code first.
Our replacement is simple: if the path being opened contains /proc/self/maps, we silently redirect it to /etc/hosts — an innocuous file that will yield an empty (or harmless) list of lines. Any other path is passed through to the real fopen untouched.
Note: We save a reference to the original
fopenas aNativeFunctionbefore replacing it. This is critical — if we calledfopendirectly inside the replacement without going through theNativeFunctionwrapper, we’d recurse infinitely back into our own hook.
function blindMaps(){
send(`[+] Trying to blind maps check...`)
const fopenPtr = Module.findGlobalExportByName("fopen"); // find fopen symbol exported by libc
const fopen = new NativeFunction(fopenPtr, 'pointer', ['pointer', 'pointer']); // create NativeFunction wrapper for fopen
Interceptor.replace(fopenPtr, new NativeCallback(function (pathPtr, modePtr) { // replace fopen with our own function
const path = pathPtr.readUtf8String(); // First argument to fopen is the path to the file, read it
// If the path contains "/proc/self/maps", replace it with "/etc/hosts"
if (path !== null && path.indexOf("/proc/self/maps") !== -1) {
const fakePath = Memory.allocUtf8String("/etc/hosts"); // Allocate memory for the fake path
return fopen(fakePath, modePtr); // Call the original fopen with the fake path
}
return fopen(pathPtr, modePtr); // Call the original fopen with the original path
}, 'pointer', ['pointer', 'pointer']));
hookNativeLib('libfoo.so', bypassNDKAntiTamper);
}
With the maps check blinded, blindMaps then calls hookNativeLib('libfoo.so', bypassNDKAntiTamper) to set up the next stage.
Stage 2: Waiting for the Library
This is a small but essential utility function that solves a timing problem.
Our script runs during the early startup of the process. At that moment, libfoo.so may not yet be loaded into memory. If we tried to hook functions inside it immediately, Process.getModuleByName would throw an error.
hookNativeLib handles both cases:
- If the module is already loaded (
Process.findModuleByNamereturns non-null), we call the callback immediately. - If it isn’t loaded yet, we hook
android_dlopen_ext— the Android-specific variant ofdlopen(seeman dlopenon Linux) that the runtime uses to load native libraries. Every time any library is loaded, ouronLeavehook fires. We check whether the successfully loaded library’s path contains our target name, and if so, we fire the callback.
The onLeave check on retval.isNull() is important: dlopen returns NULL on failure. We only want to call our callback if the library loaded successfully.
This pattern — hook the dynamic linker to defer work until a library is ready — is a fundamental Frida technique when dealing with lazily-loaded native code.
// Take the name of the library and the callback to execute as parameters
function hookNativeLib(name, callback) {
// If the library is already loaded, call the callback immediately
if (Process.findModuleByName(name)) {
callback(name);
return;
}
// Find the address of android_dlopen_ext
const android_dlopen_ext = Module.findGlobalExportByName("android_dlopen_ext");
if (android_dlopen_ext) {
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
// First argument to android_dlopen_ext is the path to the library
this.path = args[0].readUtf8String();
},
// When the library is loaded, check if the path contains the target name
onLeave: function (retval) {
if (!retval.isNull() && this.path && this.path.indexOf(name) !== -1) {
send(`[+] Caught dynamic linker loading: ${name}`);
// Call the callback with the name of the library
callback(name);
}
}
});
}
}
Stage 3: Defeating the NDK Anti-Tamper
Now that libfoo.so is loaded, we can operate directly on its code in memory.
Android’s Address Space Layout Randomization (ASLR) means the library is loaded at a different base address on every run.
However, ASLR only slides the base — the relative offsets of functions within a library never change. This means that if Ghidra shows a function at address 0x001037c0, its actual runtime address is always module.base + 0x37c0.
By analyzing libfoo.so in Ghidra beforehand, we identified two particularly hostile functions:
FUN_001037c0(offset0x37c0): The Frida detection routine. This function scans process state to determine if Frida is attached. We replace its entire body with an empty no-op —'void', []means it takes no arguments and returns nothing.
void FUN_001037c0(void)
{
FILE *__stream;
char *pcVar1;
char acStack_238 [520];
__stream = fopen("/proc/self/maps","r");
if (__stream == (FILE *)0x0) {
LAB_0010386c:
pcVar1 = "Error opening /proc/self/maps! Terminating...";
}
else {
do {
while (pcVar1 = fgets(acStack_238,0x200,__stream), pcVar1 == (char *)0x0) {
fclose(__stream);
usleep(500);
__stream = fopen("/proc/self/maps","r");
if (__stream == (FILE *)0x0) goto LAB_0010386c;
}
pcVar1 = strstr(acStack_238,"frida");
} while ((pcVar1 == (char *)0x0) &&
(pcVar1 = strstr(acStack_238,"xposed"), pcVar1 == (char *)0x0));
pcVar1 = "Tampering detected! Terminating...";
}
__android_log_print(2,"UnCrackable3",pcVar1);
/* WARNING: Subroutine does not return */
goodbye();
}
FUN_00103910(offset0x3910): The library forks a child process that immediately attaches to the parent using ptrace. This effectively “locks” the parent, as Linux only allows one tracer per process, blocking any external debuggers from attaching. Meanwhile, the parent process spawns a secondary thread (FUN_00103900).
void FUN_00103910(void)
{
__pid_t _Var1;
uint __pid;
long lVar2;
long in_FS_OFFSET;
uint local_20 [2];
long local_18;
local_18 = *(long *)(in_FS_OFFSET + 0x28);
_Var1 = fork();
if (_Var1 == 0) {
__pid = getppid();
lVar2 = ptrace(PTRACE_ATTACH,(ulong)__pid,0,0);
if (lVar2 == 0) {
waitpid(__pid,(int *)local_20,0);
ptrace(PTRACE_CONT,(ulong)__pid,0,0);
_Var1 = waitpid(__pid,(int *)local_20,0);
if (_Var1 != 0) {
do {
if ((local_20[0] & 0x7f) != 0x7f) {
/* WARNING: Subroutine does not return */
_exit(0);
}
ptrace(PTRACE_CONT,(ulong)__pid,0,0);
_Var1 = waitpid(__pid,(int *)local_20,0);
} while (_Var1 != 0);
}
}
}
else {
pthread_create((pthread_t *)local_20,(pthread_attr_t *)0x0,FUN_00103900,(void *)0x0);
}
if (*(long *)(in_FS_OFFSET + 0x28) == local_18) {
return;
}
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
Finding the goodbye Export
Unlike the two functions above — which were found through static analysis and referenced by raw offset — goodbye is an exported symbol. This means we don’t need a hardcoded offset; we can find it by name at runtime using module.enumerateExports().
The function’s name is self-explanatory: it’s a kill-switch that terminates the app when certain conditions aren’t met. We replace it with a no-op as well.
With these three replacements in place, libfoo.so is effectively defanged. bypassNDKAntiTamper then calls disableJavaAntiTamper().
function bypassNDKAntiTamper(name) {
const module = Process.getModuleByName(name); // Get the base address of the library
const baseAddress = module.base;
const offsetAddressOfFork = 0x3910; // Offset of the fork function
const offsetOfFridaDetect = 0x37c0; // Offset of the Frida detection function
const addressOfFork = baseAddress.add(offsetAddressOfFork); // Real address of the fork function
const addressOfFridaDetect = baseAddress.add(offsetOfFridaDetect); // Real address of the Frida detection function
// Replace both functions with no-ops
Interceptor.replace(addressOfFridaDetect, new NativeCallback(() => {
send(`[+] Nuked FUN_001037c0 at real address ${addressOfFridaDetect}`);
}, 'void', []));
Interceptor.replace(addressOfFork, new NativeCallback(() => {
send(`[+] Nuked FUN_00103910 at real address ${addressOfFork}`);
}, 'void', []));
const exports = module.enumerateExports(); // Get all exports from libfoo.so
const goodByeFunction = exports.filter(e => e.name.includes('goodbye')); // Filter for goodbye function
if (goodByeFunction.length > 0) {
const goodbyeAddr = goodByeFunction[0].address; // Get the address of the goodbye function
send(`[+] Found ${goodByeFunction[0].name} at address ${goodbyeAddr}`);
Interceptor.replace(goodbyeAddr, new NativeCallback(() => { // Replace the goodbye function with a no-op
send(`[+] Blocked goodbye() from crashing the app!`);
}, 'void', []));
}
disableJavaAntiTamper()
}
Stage 4: Disabling Java Anti-Tamper
With the native layer neutered, we can safely patch the Java layer.
Java.use gives us a reference to a Java class. From there, we override method implementations with our own implementations — the same principle as Interceptor.replace but at the Java bytecode level:
IntegrityCheck.isDebuggable: Returnstrueif the app is running in a debuggable context. We force it to always returnfalse.RootDetection.checkRoot1/2/3: Three checks for root indicators (e.g.subinary existence, test-keys build). We force all three to returnfalse.MainActivity.verifyLibs: The app verifies that its native libraries haven’t been tampered with viaCRC. We replace the method body with nothing.MainActivity$2.onPostExecute: An anonymousAsyncTaskinner class that runs a debugger check asynchronously. We neutralize itsonPostExecuteso the result of that check is never acted upon.



Why do we do this after bypassing the native layer?
The Java anti-tamper checks are triggered duringActivity.onCreate. Iflibfoo.sohadn’t been loaded and its own checks neutralized first, the app would have already crashed before we’d have a chance to intercept anything on the Java side. The ordering of the call chain is not arbitrary — it reflects the app’s own initialization sequence.
function disableJavaAntiTamper(){
Java.perform(() => {
// Get a reference to the IntegrityCheck class
const integrityCheckClassRef = Java.use('sg.vantagepoint.util.IntegrityCheck');
// Get a reference to the RootDetection class
const rootCheckClassRef = Java.use('sg.vantagepoint.util.RootDetection');
// Replace the isDebuggable method with our own implementation
integrityCheckClassRef.isDebuggable.overload('android.content.Context').implementation = (context) => {
send('[+] Nuked sg.vantagepoint.util.IntegrityCheck.isDebuggable');
return false
}
// Replace the checkRoot1 method with our own implementation
rootCheckClassRef.checkRoot1.overload().implementation = () => {
send(`[+] Nuked 'sg.vantagepoint.util.RootDetection.checkRoot1'`)
return false
}
// Replace the checkRoot2 method with our own implementation
rootCheckClassRef.checkRoot2.overload().implementation = () => {
send(`[+] Nuked 'sg.vantagepoint.util.RootDetection.checkRoot2'`)
return false
}
// Replace the checkRoot3 method with our own implementation
rootCheckClassRef.checkRoot3.overload().implementation = () => {
send(`[+] Nuked 'sg.vantagepoint.util.RootDetection.checkRoot3'`)
return false
}
// Get a reference to the MainActivity class
const MainActivity = Java.use('sg.vantagepoint.uncrackable3.MainActivity');
// Replace the verifyLibs method with our own implementation
MainActivity.verifyLibs.implementation = function() {
send(`[+] Nuked 'sg.vantagepoint.uncrackable3.MainActivity.verifyLibs'`);
};
const AntiDebugTask = Java.use('sg.vantagepoint.uncrackable3.MainActivity$2');
// Replace the onPostExecute method with our own implementation
AntiDebugTask.onPostExecute.overload('java.lang.String').implementation = function(str) {
send("[+] Neutered MainActivity$2.onPostExecute() - Debugger check bypassed!");
};
})
exploit()
}
Stage 5: Extracting the Secret
function exploit(){
const FUN_001012c0Offset = 0x12c0
const module = Process.getModuleByName('libfoo.so');
const FUN_001012c0OAddress = module.base.add(FUN_001012c0Offset);
let xor_key = null
let FUN_001012c0OArrayBuf = null
const numBytes = 24
Java.perform(() => {
xor_key = Java.use('sg.vantagepoint.uncrackable3.MainActivity').xorkey.value;
send(`[+] - Got secret key (xorkey): ${xor_key}`)
})
Interceptor.attach(FUN_001012c0OAddress, {
onEnter: (args) => {
send(`Entering FUN_001012c0O and saving the input buffer...`)
FUN_001012c0OArrayBuf = args[0]
},
onLeave(ret) {
const buff = FUN_001012c0OArrayBuf.readByteArray(numBytes)
send(`[+] Hexdump of the input buffer on exit: '${hexdump(buff, { length: numBytes, ansi: true })}'`);
const secret_key = new Uint8Array(buff)
let str = "";
for(let i = 0; i < secret_key.length; i++) {
str += (secret_key[i].toString(16) + " ");
}
const secret = []
for (let i =0;i<numBytes;i++){
secret[i] = String.fromCharCode(secret_key[i] ^ xor_key.charCodeAt(i));
}
send(`Exiting FUN_001012c0O with exit value '${ret}'...Secret key: '${secret.join('')}'...xor_key: '${xor_key}'`)
}
})
}
All previous stages were defensive: we were removing obstacles. This is where we actually extract the secret.
Reading the XOR Key
The app stores a static XOR key in a Java static field: MainActivity.xorkey. This field is accessible at runtime via Java.use(...).xorkey.value. We read it immediately, before hooking the native function, since we need it ready for when the decryption happens.
Hooking the secret generation
Static analysis in Ghidra revealed that the function undefined *Java_sg_vantagepoint_uncrackable3_CodeCheck_bar(long *param_1,undefined8 param_2,undefined8 param_3) is responsible for validating our input.
undefined *
Java_sg_vantagepoint_uncrackable3_CodeCheck_bar(long *param_1,undefined8 param_2,undefined8 param_3)
{
int iVar1;
long lVar2;
undefined *puVar3;
ulong uVar4;
long in_FS_OFFSET;
byte local_48 [40];
long local_20;
local_20 = *(long *)(in_FS_OFFSET + 0x28);
local_48[0x10] = 0;
local_48[0x11] = 0;
local_48[0x12] = 0;
local_48[0x13] = 0;
local_48[0x14] = 0;
local_48[0x15] = 0;
local_48[0x16] = 0;
local_48[0x17] = 0;
local_48[0x18] = 0;
local_48[0] = 0;
local_48[1] = 0;
local_48[2] = 0;
local_48[3] = 0;
local_48[4] = 0;
local_48[5] = 0;
local_48[6] = 0;
local_48[7] = 0;
local_48[8] = 0;
local_48[9] = 0;
local_48[10] = 0;
local_48[0xb] = 0;
local_48[0xc] = 0;
local_48[0xd] = 0;
local_48[0xe] = 0;
local_48[0xf] = 0;
if (DAT_0010705c == 2) {
FUN_001012c0(local_48);
lVar2 = (**(code **)(*param_1 + 0x5c0))(param_1,param_3,0);
iVar1 = (**(code **)(*param_1 + 0x558))(param_1,param_3);
if (iVar1 == 0x18) {
uVar4 = 0;
do {
if (((*(byte *)(lVar2 + uVar4) != ((&DAT_00107040)[uVar4] ^ local_48[uVar4])) ||
(*(byte *)(lVar2 + 1 + uVar4) != ((&DAT_00107041)[uVar4] ^ local_48[uVar4 + 1]))) ||
(*(byte *)(lVar2 + 2 + uVar4) != ((&DAT_00107042)[uVar4] ^ local_48[uVar4 + 2])))
goto LAB_00103b1b;
uVar4 = uVar4 + 3;
} while (uVar4 < 0x18);
puVar3 = &DAT_00107001;
if ((int)uVar4 == 0x18) goto LAB_00103b1d;
}
}
LAB_00103b1b:
puVar3 = (undefined *)0x0;
LAB_00103b1d:
if (*(long *)(in_FS_OFFSET + 0x28) == local_20) {
return puVar3;
}
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
Looking a bit closer into it, we can see that it’s actually FUN_001012c0 that’s responsible for generating the secret string.
Click to view a rather long and complex FUN_001012c0 decompiled code
void FUN_001012c0(undefined8 *param_1)
{
uint *puVar1;
uint *puVar2;
long lVar3;
lVar3 = DAT_00107008 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = (uint *)&_1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
}
else {
puVar2 = _1_sub_doit__opaque_list1_1 + 2;
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
}
*(uint **)puVar2 = puVar1;
}
lVar3 = lVar3 * 0x41c64e6d + 0x3039;
DAT_00107008 = lVar3;
puVar1 = malloc(0x10);
if (puVar1 != (uint *)0x0) {
*puVar1 = (uint)lVar3 & 0x7fffffff;
puVar2 = _1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 == (uint *)0x0) {
*(uint **)(puVar1 + 2) = puVar1;
_1_sub_doit__opaque_list1_1 = puVar1;
}
else {
*(undefined8 *)(puVar1 + 2) = *(undefined8 *)(_1_sub_doit__opaque_list1_1 + 2);
*(uint **)(puVar2 + 2) = puVar1;
}
}
_1_sub_doit__opaque_list2_1 = _1_sub_doit__opaque_list1_1;
if (_1_sub_doit__opaque_list1_1 != (uint *)0x0) {
*(undefined8 *)((long)param_1 + 9) = 0;
*(undefined8 *)((long)param_1 + 0x11) = 0;
*param_1 = 0;
param_1[1] = 0;
*param_1 = 0x1549170f1311081d;
param_1[1] = 0x15131d5a1903000d;
param_1[2] = 0x14130817005a0e08;
}
return;
}
What we’ll do is the following: We’ll attach to the function, intercept the parameter that it receives, and then we’ll print it out to the console and decode it on exit of the function
We use Interceptor.attach (rather than Interceptor.replace) because we don’t want to disable this function — we want to observe it while it still does its work:
onEnter: We save the buffer pointer (args[0]) intoFUN_001012c0OArrayBuf. We can’t read the buffer yet because the decryption hasn’t happened.onLeave: The function has finished. The buffer now contains the decrypted bytes. We read exactly 24 bytes from it withreadByteArray.
Decrypting
The “decrypted” buffer coming out of the native function is still XOR-encoded against xorkey. We undo this with a simple loop: for each byte i of the buffer, XOR it against the i-th character of xorkey. The result is the plaintext secret string, which we assemble character by character and send back.
function exploit(){
const FUN_001012c0Offset = 0x12c0 // offset of the function responsible for generating the secret.
const module = Process.getModuleByName('libfoo.so');
const FUN_001012c0OAddress = module.base.add(FUN_001012c0Offset); // Getting real time address of the function
let xor_key = null // We'll store the xor key which is a static variable on the MainActivity class
let FUN_001012c0OArrayBuf = null // We'll store the reference to buffer on enter and read it on leave
// Notice the checks in Java_sg_vantagepoint_uncrackable3_CodeCheck_bar (if iVar1 == 0x18)...Whatever
// The secret is, it's 24 bytes long. Or in hex 0x18
const numBytes = 24
// #### Extracting JVM side XOR key
Java.perform(() => {
xor_key = Java.use('sg.vantagepoint.uncrackable3.MainActivity').xorkey.value;
send(`[+] - Got secret key (xorkey): ${xor_key}`)
})
// Attach to our target function with Interceptor attach
Interceptor.attach(FUN_001012c0OAddress, {
onEnter: (args) => {
send(`Entering FUN_001012c0O and saving the input buffer...`)
// Store the reference to parameter buffer
FUN_001012c0OArrayBuf = args[0]
},
onLeave(ret) {
// When FUN_001012c0O exits read 24 bytes
const buff = FUN_001012c0OArrayBuf.readByteArray(numBytes)
send(`[+] Hexdump of the input buffer on exit: '${hexdump(buff, { length: numBytes, ansi: true })}'`);
const secret_key = new Uint8Array(buff)
let str = "";
// Convert to readable characters
for(let i = 0; i < secret_key.length; i++) {
str += (secret_key[i].toString(16) + " ");
}
// XOR the secret with the xor_key
const secret = []
for (let i =0;i<numBytes;i++){
secret[i] = String.fromCharCode(secret_key[i] ^ xor_key.charCodeAt(i));
}
// And we are done!
send(`Exiting FUN_001012c0O with exit value '${ret}'...Secret key: '${secret.join('')}'...xor_key: '${xor_key}'`)
}
})
}
Putting It All Together
The entire chain, triggered by a single call to blindMaps() at the bottom of the script, automatically unravels the application’s layered defenses in the correct order:
| Stage | What we do | Frida primitive used |
|---|---|---|
| 1 — Maps blinding | Redirect /proc/self/maps opens to /etc/hosts | Interceptor.replace + NativeCallback |
| 2 — Library hooking | Wait for libfoo.so to load via android_dlopen_ext | Interceptor.attach on dynamic linker |
| 3 — NDK bypass | No-op the Frida detector, fork watchdog, and goodbye kill-switch | Interceptor.replace at computed ASLR addresses |
| 4 — Java bypass | Override root checks, debuggability check, and library verifier | Java.use + .implementation override |
| 5 — Secret extraction | Read XOR key from Java field; intercept decryption buffer | Interceptor.attach + readByteArray |
Each layer had to be bypassed in a specific order, and that order was dictated by the application’s own startup sequence — something that only becomes clear once you understand both the static structure and the runtime behavior of the target.
Dynamic analysis with Frida is not about brute force; it’s about finding the right moment to intervene and doing the minimum necessary to let the application run itself into a position where the secret is in plain sight.
Here’s a recording of a working PoC (click on the video to enlarge):
Here is the whole PoC script
function hookNativeLib(name, callback) {
if (Process.findModuleByName(name)) {
callback(name);
return;
}
const android_dlopen_ext = Module.findGlobalExportByName("android_dlopen_ext");
if (android_dlopen_ext) {
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
this.path = args[0].readUtf8String();
},
onLeave: function (retval) {
if (!retval.isNull() && this.path && this.path.indexOf(name) !== -1) {
send(`[+] Caught dynamic linker loading: ${name}`);
callback(name);
}
}
});
}
}
function blindMaps(){
send(`[+] Trying to blind maps check...`)
const fopenPtr = Module.findGlobalExportByName("fopen");
const fopen = new NativeFunction(fopenPtr, 'pointer', ['pointer', 'pointer']);
Interceptor.replace(fopenPtr, new NativeCallback(function (pathPtr, modePtr) {
const path = pathPtr.readUtf8String();
if (path !== null && path.indexOf("/proc/self/maps") !== -1) {
const fakePath = Memory.allocUtf8String("/etc/hosts");
return fopen(fakePath, modePtr);
}
return fopen(pathPtr, modePtr);
}, 'pointer', ['pointer', 'pointer']));
hookNativeLib('libfoo.so', bypassNDKAntiTamper);
}
function bypassNDKAntiTamper(name) {
const module = Process.getModuleByName(name);
const baseAddress = module.base;
const offsetAddressOfFork = 0x3910;
const offsetOfFridaDetect = 0x37c0;
const addressOfFork = baseAddress.add(offsetAddressOfFork);
const addressOfFridaDetect = baseAddress.add(offsetOfFridaDetect);
Interceptor.replace(addressOfFridaDetect, new NativeCallback(() => {
send(`[+] Nuked FUN_001037c0 at real address ${addressOfFridaDetect}`);
}, 'void', []));
Interceptor.replace(addressOfFork, new NativeCallback(() => {
send(`[+] Nuked FUN_00103910 at real address ${addressOfFork}`);
}, 'void', []));
const exports = module.enumerateExports();
const goodByeFunction = exports.filter(e => e.name.includes('goodbye'));
if (goodByeFunction.length > 0) {
const goodbyeAddr = goodByeFunction[0].address;
send(`[+] Found ${goodByeFunction[0].name} at address ${goodbyeAddr}`);
Interceptor.replace(goodbyeAddr, new NativeCallback(() => {
send(`[+] Blocked goodbye() from crashing the app!`);
}, 'void', []));
} else {
send("[-] No goodbye function found");
}
disableJavaAntiTamper()
}
function disableJavaAntiTamper(){
Java.perform(() => {
const integrityCheckClassRef = Java.use('sg.vantagepoint.util.IntegrityCheck');
const rootCheckClassRef = Java.use('sg.vantagepoint.util.RootDetection');
integrityCheckClassRef.isDebuggable.overload('android.content.Context').implementation = (context) => {
send('[+] Nuked sg.vantagepoint.util.IntegrityCheck.isDebuggable');
return false
}
rootCheckClassRef.checkRoot1.overload().implementation = () => {
send(`[+] Nuked 'sg.vantagepoint.util.RootDetection.checkRoot1'`)
return false
}
rootCheckClassRef.checkRoot2.overload().implementation = () => {
send(`[+] Nuked 'sg.vantagepoint.util.RootDetection.checkRoot2'`)
return false
}
rootCheckClassRef.checkRoot3.overload().implementation = () => {
send(`[+] Nuked 'sg.vantagepoint.util.RootDetection.checkRoot3'`)
return false
}
const MainActivity = Java.use('sg.vantagepoint.uncrackable3.MainActivity');
MainActivity.verifyLibs.implementation = function() {
send(`[+] Nuked 'sg.vantagepoint.uncrackable3.MainActivity.verifyLibs'`);
};
const AntiDebugTask = Java.use('sg.vantagepoint.uncrackable3.MainActivity$2');
AntiDebugTask.onPostExecute.overload('java.lang.String').implementation = function(str) {
send("[+] Neutered MainActivity$2.onPostExecute() - Debugger check bypassed!");
};
})
exploit()
}
function exploit(){
const FUN_001012c0Offset = 0x12c0
const module = Process.getModuleByName('libfoo.so');
const FUN_001012c0OAddress = module.base.add(FUN_001012c0Offset);
let xor_key = null
let FUN_001012c0OArrayBuf = null
const numBytes = 24
Java.perform(() => {
xor_key = Java.use('sg.vantagepoint.uncrackable3.MainActivity').xorkey.value;
send(`[+] - Got secret key (xorkey): ${xor_key}`)
})
Interceptor.attach(FUN_001012c0OAddress, {
onEnter: (args) => {
send(`Entering FUN_001012c0O and saving the input buffer...`)
FUN_001012c0OArrayBuf = args[0]
},
onLeave(ret) {
const buff = FUN_001012c0OArrayBuf.readByteArray(numBytes)
send(`[+] Hexdump of the input buffer on exit: '${hexdump(buff, { length: numBytes, ansi: true })}'`);
const secret_key = new Uint8Array(buff)
let str = "";
for(let i = 0; i < secret_key.length; i++) {
str += (secret_key[i].toString(16) + " ");
}
const secret = []
for (let i =0;i<numBytes;i++){
secret[i] = String.fromCharCode(secret_key[i] ^ xor_key.charCodeAt(i));
}
send(`Exiting FUN_001012c0O with exit value '${ret}'...Secret key: '${secret.join('')}'...xor_key: '${xor_key}'`)
}
})
}
blindMaps()