InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

Follow publication

Flutter Hackers: Uncovering the Dev’s Myopia (Part 2)

Felix Alexander
InfoSec Write-ups
Published in
19 min readMar 18, 2023

Not all Flutter Applications are hard to be statically analyzed and to spot a vulnerability itself, we may also began to include the used package as an in-scope variable of the black-box testing demand.

A Preamble

Prior Concept

flutter build apk --release
extra-gen-snapshot-options=--obfuscate
flutter build apk --release --obfuscate
Image taken from : https://medium.com/@.Qubit/symmetric-key-algorithm-in-cryptography-3d839bba8613

The Nomenclature of Analysis

adb install -g <path-to-the-apk.apk>
apktool d <your-path-to-flutter.apk>
 if ver>27:
replaceFileText('src/third_party/dart/runtime/vm/class_table.cc','::Print() {','::Print() { OS::PrintErr("reFlutter");\n char pushArr[60000]="";\n')
replaceFileText('src/flutter/BUILD.gn',' if (is_android) {\n public_deps +=\n [ "//flutter/shell/platform/android:flutter_shell_native_unittests" ]\n }','')
replaceFileText('src/third_party/dart/runtime/vm/class_table.cc','OS::PrintErr("%" Pd ": %s\\n", i, name.ToCString());','\n auto& funcs = Array::Handle(cls.functions()); if (funcs.Length()>1000) { continue; } char classText[100000]=""; String& supname = String::Handle(); name = cls.Name(); strcat(classText,cls.ToCString()); Class& supcls = Class::Handle(); supcls = cls.SuperClass(); if (!supcls.IsNull()) { supname = supcls.Name(); strcat(classText," extends "); strcat(classText,supname.ToCString()); } const auto& interfaces = Array::Handle(cls.interfaces()); auto& interface = Instance::Handle(); for (intptr_t in = 0;in < interfaces.Length(); in++) { interface^=interfaces.At(in); if(in==0){strcat(classText," implements ");} if(in>0){strcat(classText," , ");} strcat(classText,interface.ToCString()); } strcat(classText," {\\n"); const auto& fields = Array::Handle(cls.fields()); auto& field = Field::Handle(); auto& fieldType = AbstractType::Handle(); String& fieldTypeName = String::Handle(); String& finame = String::Handle(); Instance& instance2 = Instance::Handle(); for (intptr_t f = 0; f < fields.Length(); f++) { field ^= fields.At(f); finame = field.name(); fieldType = field.type(); fieldTypeName = fieldType.Name(); strcat(classText," "); strcat(classText,fieldTypeName.ToCString()); strcat(classText," "); strcat(classText,finame.ToCString()); if(field.is_static()){ instance2 ^= field.StaticValue(); strcat(classText," = "); strcat(classText,instance2.ToCString()); strcat(classText," ;\\n"); } else { strcat(classText," = "); strcat(classText," nonstatic;\\n"); } } for (intptr_t c = 0; c < funcs.Length(); c++) { auto& func = Function::Handle(); func = cls.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.InternalSignature();auto& codee = Code::Handle(func.CurrentCode()); if(!func.IsLocalFunction()) { strcat(classText," \\n "); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n "); char append[70]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.InternalSignature(); strcat(classText," \\n "); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n "); char append[80]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } } strcat(classText," \\n }\\n\\n"); const Library& libr = Library::Handle(cls.library());if (!libr.IsNull()) { auto& owner_class = Class::Handle(); owner_class = libr.toplevel_class(); auto& funcsTopLevel = Array::Handle(owner_class.functions()); char pushTmp[1000]; String& owner_name = String::Handle(); owner_name = libr.url(); sprintf(pushTmp,"\'%s\',",owner_name.ToCString()); if (funcsTopLevel.Length()>0&&strstr(pushArr, pushTmp) == NULL) { strcat(pushArr,pushTmp); strcat(classText,"Library:"); strcat(classText,pushTmp); strcat(classText," {\\n"); for (intptr_t c = 0; c < funcsTopLevel.Length(); c++) { auto& func = Function::Handle(); func = owner_class.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.InternalSignature(); auto& codee = Code::Handle(func.CurrentCode()); if(!func.IsLocalFunction()) { strcat(classText," \\n "); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n "); char append[70]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.InternalSignature(); strcat(classText," \\n "); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n "); char append[80]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } } strcat(classText," \\n }\\n\\n");}} struct stat entry_info; int exists = 0; if (stat("/data/data/", &entry_info)==0 && S_ISDIR(entry_info.st_mode)){ exists=1; } if(exists==1){ pid_t pid = getpid(); char path[64] = { 0 }; sprintf(path, "/proc/%d/cmdline", pid); FILE *cmdline = fopen(path, "r"); if (cmdline) { char chm[264] = { 0 }; char pat[264] = { 0 }; char application_id[64] = { 0 }; fread(application_id, sizeof(application_id), 1, cmdline); sprintf(pat, "/data/data/%s/dump.dart", application_id); do { FILE *f = fopen(pat, "a+"); fprintf(f, "%s",classText); fflush(f); fclose(f); sprintf(chm,"/data/data/%s",application_id); chmod(chm, S_IRWXU|S_IRWXG|S_IRWXO); chmod(pat, S_IRWXU|S_IRWXG|S_IRWXO); } while (0); fclose(cmdline); } } if(exists==0){ char pat[264] = { 0 }; sprintf(pat, "%s/Documents/dump.dart", getenv("HOME")); OS::PrintErr("reFlutter dump file: %s",pat); do { FILE *f = fopen(pat, "a+"); fprintf(f, "%s",classText); fflush(f); fclose(f); } while (0); }')
#replaceFileText('src/third_party/dart/runtime/vm/class_table.cc','OS::PrintErr("%" Pd ": %s\\n", i, name.ToCString());','auto& funcs = Array::Handle(cls.functions()); if (funcs.Length()>1000) { continue; } char classText[65000]=""; String& supname = String::Handle(); name = cls.Name(); strcat(classText," "); strcat(classText,cls.ToCString()); Class& supcls = Class::Handle(); supcls = cls.SuperClass(); if (!supcls.IsNull()) { supname = supcls.Name(); strcat(classText," extends "); strcat(classText,supname.ToCString()); } const auto& interfaces = Array::Handle(cls.interfaces()); auto& interface = Instance::Handle(); for (intptr_t in = 0;in < interfaces.Length(); in++) { interface^=interfaces.At(in); if(in==0){strcat(classText," implements ");} if(in>0){strcat(classText," , ");} strcat(classText,interface.ToCString()); } strcat(classText," {\\n"); const auto& fields = Array::Handle(cls.fields()); auto& field = Field::Handle(); auto& fieldType = AbstractType::Handle(); String& fieldTypeName = String::Handle(); String& finame = String::Handle(); Instance& instance2 = Instance::Handle(); for (intptr_t f = 0; f < fields.Length(); f++) { field ^= fields.At(f); finame = field.name(); fieldType = field.type(); fieldTypeName = fieldType.Name(); strcat(classText," "); strcat(classText,fieldTypeName.ToCString()); strcat(classText," "); strcat(classText,finame.ToCString()); if(field.is_static()){ instance2 ^= field.StaticValue(); strcat(classText," = "); strcat(classText,instance2.ToCString()); strcat(classText," ;\\n"); } else { strcat(classText," = "); strcat(classText," nonstatic;\\n"); } } for (intptr_t c = 0; c < funcs.Length(); c++) { auto& func = Function::Handle(); func = cls.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.InternalSignature(); if(!func.IsLocalFunction()) { strcat(classText," \\n"); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.InternalSignature(); strcat(classText," \\n"); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n }\\n"); } } OS::PrintErr("reflutter:\\n %s \\n }\\n",classText);')
else:
replaceFileText('src/third_party/dart/runtime/vm/class_table.cc','::Print() {','::Print() { OS::PrintErr("reFlutter");\n char pushArr[60000]="";\n')
replaceFileText('src/third_party/dart/runtime/vm/class_table.cc','OS::PrintErr("%" Pd ": %s\\n", i, name.ToCString());','\n auto& funcs = Array::Handle(cls.functions()); if (funcs.Length()>1000) { continue; } char classText[100000]=""; String& supname = String::Handle(); name = cls.Name(); strcat(classText,cls.ToCString()); Class& supcls = Class::Handle(); supcls = cls.SuperClass(); if (!supcls.IsNull()) { supname = supcls.Name(); strcat(classText," extends "); strcat(classText,supname.ToCString()); } const auto& interfaces = Array::Handle(cls.interfaces()); auto& interface = Instance::Handle(); for (intptr_t in = 0;in < interfaces.Length(); in++) { interface^=interfaces.At(in); if(in==0){strcat(classText," implements ");} if(in>0){strcat(classText," , ");} strcat(classText,interface.ToCString()); } strcat(classText," {\\n"); const auto& fields = Array::Handle(cls.fields()); auto& field = Field::Handle(); auto& fieldType = AbstractType::Handle(); String& fieldTypeName = String::Handle(); String& finame = String::Handle(); Instance& instance2 = Instance::Handle(); for (intptr_t f = 0; f < fields.Length(); f++) { field ^= fields.At(f); finame = field.name(); fieldType = field.type(); fieldTypeName = fieldType.Name(); strcat(classText," "); strcat(classText,fieldTypeName.ToCString()); strcat(classText," "); strcat(classText,finame.ToCString()); if(field.is_static()){ instance2 = field.StaticValue(); strcat(classText," = "); strcat(classText,instance2.ToCString()); strcat(classText," ;\\n"); } else { strcat(classText," = "); strcat(classText," nonstatic;\\n"); } } for (intptr_t c = 0; c < funcs.Length(); c++) { auto& func = Function::Handle(); func = cls.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.Signature();auto& codee = Code::Handle(func.CurrentCode()); if(!func.IsLocalFunction()) { strcat(classText," \\n "); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n "); char append[70]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.Signature(); strcat(classText," \\n "); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n "); char append[80]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } } strcat(classText," \\n }\\n\\n"); const Library& libr = Library::Handle(cls.library());if (!libr.IsNull()) { auto& owner_class = Class::Handle(); owner_class = libr.toplevel_class(); auto& funcsTopLevel = Array::Handle(owner_class.functions()); char pushTmp[1000]; String& owner_name = String::Handle(); owner_name = libr.url(); sprintf(pushTmp,"\'%s\',",owner_name.ToCString()); if (funcsTopLevel.Length()>0&&strstr(pushArr, pushTmp) == NULL) { strcat(pushArr,pushTmp); strcat(classText,"Library:"); strcat(classText,pushTmp); strcat(classText," {\\n"); for (intptr_t c = 0; c < funcsTopLevel.Length(); c++) { auto& func = Function::Handle(); func = owner_class.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.Signature(); auto& codee = Code::Handle(func.CurrentCode()); if(!func.IsLocalFunction()) { strcat(classText," \\n "); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n "); char append[70]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.Signature(); strcat(classText," \\n "); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n "); char append[80]; sprintf(append," Code Offset: _kDartIsolateSnapshotInstructions + 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())); strcat(classText,append); strcat(classText," \\n }\\n"); } } strcat(classText," \\n }\\n\\n");}} struct stat entry_info; int exists = 0; if (stat("/data/data/", &entry_info)==0 && S_ISDIR(entry_info.st_mode)){ exists=1; } if(exists==1){ pid_t pid = getpid(); char path[64] = { 0 }; sprintf(path, "/proc/%d/cmdline", pid); FILE *cmdline = fopen(path, "r"); if (cmdline) { char chm[264] = { 0 }; char pat[264] = { 0 }; char application_id[64] = { 0 }; fread(application_id, sizeof(application_id), 1, cmdline); sprintf(pat, "/data/data/%s/dump.dart", application_id); do { FILE *f = fopen(pat, "a+"); fprintf(f, "%s",classText); fflush(f); fclose(f); sprintf(chm,"/data/data/%s",application_id); chmod(chm, S_IRWXU|S_IRWXG|S_IRWXO); chmod(pat, S_IRWXU|S_IRWXG|S_IRWXO); } while (0); fclose(cmdline); } } if(exists==0){ char pat[264] = { 0 }; sprintf(pat, "%s/Documents/dump.dart", getenv("HOME")); OS::PrintErr("reFlutter dump file: %s",pat); do { FILE *f = fopen(pat, "a+"); fprintf(f, "%s",classText); fflush(f); fclose(f); } while (0); }')
#replaceFileText('src/third_party/dart/runtime/vm/class_table.cc','OS::PrintErr("%" Pd ": %s\\n", i, name.ToCString());','#if defined(HOST_ARCH_X64) uintptr_t instrArch = 0xE000;#elif defined(HOST_ARCH_ARM64) uintptr_t instrArch = 0xF000;#else uintptr_t instrArch = 0xB000;#endif auto& funcs = Array::Handle(cls.functions()); if (funcs.Length()>1000) { continue; } char classText[100000]=""; String& supname = String::Handle(); name = cls.Name(); strcat(classText,cls.ToCString()); Class& supcls = Class::Handle(); supcls = cls.SuperClass(); if (!supcls.IsNull()) { supname = supcls.Name(); strcat(classText," extends "); strcat(classText,supname.ToCString()); } const auto& interfaces = Array::Handle(cls.interfaces()); auto& interface = Instance::Handle(); for (intptr_t in = 0;in < interfaces.Length(); in++) { interface^=interfaces.At(in); if(in==0){strcat(classText," implements ");} if(in>0){strcat(classText," , ");} strcat(classText,interface.ToCString()); } strcat(classText," {\\n"); const auto& fields = Array::Handle(cls.fields()); auto& field = Field::Handle(); auto& fieldType = AbstractType::Handle(); String& fieldTypeName = String::Handle(); String& finame = String::Handle(); Instance& instance2 = Instance::Handle(); for (intptr_t f = 0; f < fields.Length(); f++) { field ^= fields.At(f); finame = field.name(); fieldType = field.type(); fieldTypeName = fieldType.Name(); strcat(classText," "); strcat(classText,fieldTypeName.ToCString()); strcat(classText," "); strcat(classText,finame.ToCString()); if(field.is_static()){ instance2 = field.StaticValue(); strcat(classText," = "); strcat(classText,instance2.ToCString()); strcat(classText," ;\\n"); } else { strcat(classText," = "); strcat(classText," nonstatic;\\n"); } } for (intptr_t c = 0; c < funcs.Length(); c++) { auto& func = Function::Handle(); func = cls.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.Signature();auto& codee = Code::Handle(func.CurrentCode()); if(!func.IsLocalFunction()) { strcat(classText," \\n "); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n "); char append[70]; sprintf(append," Code Offset: 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())+ instrArch); strcat(classText,append); strcat(classText," \\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.Signature(); strcat(classText," \\n "); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n "); char append[50]; sprintf(append," Code Offset: 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint()) + instrArch); strcat(classText,append); strcat(classText," \\n }\\n"); } } strcat(classText," \\n }\\n\\n"); const Library& libr = Library::Handle(cls.library());if (!libr.IsNull()) { auto& owner_class = Class::Handle(); owner_class = libr.toplevel_class(); auto& funcsTopLevel = Array::Handle(owner_class.functions()); char pushTmp[1000]; String& owner_name = String::Handle(); owner_name = libr.url(); sprintf(pushTmp,"\'%s\',",owner_name.ToCString()); if (funcsTopLevel.Length()>0&&strstr(pushArr, pushTmp) == NULL) { strcat(pushArr,pushTmp); strcat(classText,"Library:"); strcat(classText,pushTmp); strcat(classText," {\\n"); for (intptr_t c = 0; c < funcsTopLevel.Length(); c++) { auto& func = Function::Handle(); func = owner_class.FunctionFromIndex(c); String& signature = String::Handle(); signature = func.Signature(); auto& codee = Code::Handle(func.CurrentCode()); if(!func.IsLocalFunction()) { strcat(classText," \\n "); strcat(classText,func.ToCString()); strcat(classText," "); strcat(classText,signature.ToCString()); strcat(classText," { \\n\\n "); char append[70]; sprintf(append," Code Offset: 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint())+ instrArch); strcat(classText,append); strcat(classText," \\n }\\n"); } else { auto& parf = Function::Handle(); parf=func.parent_function(); String& signParent = String::Handle(); signParent = parf.Signature(); strcat(classText," \\n "); strcat(classText,parf.ToCString()); strcat(classText," "); strcat(classText,signParent.ToCString()); strcat(classText," { \\n\\n "); char append[50]; sprintf(append," Code Offset: 0x%016" PRIxPTR "\\n",static_cast<uintptr_t>(codee.MonomorphicUncheckedEntryPoint()) + instrArch); strcat(classText,append); strcat(classText," \\n }\\n"); } } strcat(classText," \\n }\\n\\n");}} struct stat entry_info; int exists = 0; if (stat("/data/data/", &entry_info)==0 && S_ISDIR(entry_info.st_mode)){ exists=1; } if(exists==1){ pid_t pid = getpid(); char path[64] = { 0 }; sprintf(path, "/proc/%d/cmdline", pid); FILE *cmdline = fopen(path, "r"); if (cmdline) { char chm[264] = { 0 }; char pat[264] = { 0 }; char application_id[64] = { 0 }; fread(application_id, sizeof(application_id), 1, cmdline); sprintf(pat, "/data/data/%s/dump.dart", application_id); do { FILE *f = fopen(pat, "a+"); fprintf(f, "%s",classText); fflush(f); fclose(f); sprintf(chm,"/data/data/%s",application_id); chmod(chm, S_IRWXU|S_IRWXG|S_IRWXO); chmod(pat, S_IRWXU|S_IRWXG|S_IRWXO); } while (0); fclose(cmdline); } } if(exists==0){ char pat[264] = "/tmp/dump.dart"; do { FILE *f = fopen(pat, "a+"); fprintf(f, "%s",classText); fflush(f); fclose(f); } while (0); }')
replaceFileText('src/third_party/dart/tools/make_version.py','snapshot_hash = MakeSnapshotHashString()', 'snapshot_hash = \''+hashS+'\'')
replaceFileText('src/third_party/dart/runtime/bin/socket.cc','DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);', 'DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);Syslog::PrintErr("ref: %s",inet_ntoa(addr.in.sin_addr));if(port>50){port=8083;addr.addr.sa_family=AF_INET;addr.in.sin_family=AF_INET;inet_aton("192.168.133.104", &addr.in.sin_addr);}')
replaceFileText('src/third_party/boringssl/src/ssl/ssl_x509.cc','static bool ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,\n SSL_HANDSHAKE *hs,\n uint8_t *out_alert) {', 'static bool ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,\n SSL_HANDSHAKE *hs,\n uint8_t *out_alert) {return true;')
replaceFileText('src/third_party/boringssl/src/ssl/ssl_x509.cc','static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,\n
Library:'package:pwndroid/main.dart' Class: _MyHomePageState@806319839 extends State {

Function 'compare':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000188164

}

Function 'encrypt':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000185418

}

Function 'prepare':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000184cd0

}

Function 'build':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000184a78

}

}

Library:'package:pwndroid/main.dart', {

Function 'main': static. () => void {

Code Offset: _kDartIsolateSnapshotInstructions + 0x000000000024b0f0

}

}
Library:'package:encrypt/encrypt.dart' Class: Encrypter extends Object {

Function 'encryptBytes':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000185544

}

Function 'encrypt':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000188210

}

}

Library:'package:encrypt/encrypt.dart' Class: Encrypted extends Object {

Function 'Encrypted.fromUtf8': constructor. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000002664

}

Function 'Encrypted.fromLength': constructor. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000002664

}

Function 'get:base64':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x00000000001881cc

}

Function '==':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x00000000001ea96c

}

}

Library:'package:encrypt/encrypt.dart' Class: Key extends Encrypted {

Function 'Key.fromLength': constructor. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000002664

}

}

Library:'package:encrypt/encrypt.dart' Class: IV extends Encrypted {

Function 'IV.fromUtf8': constructor. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000002664

}

}

Library:'package:encrypt/encrypt.dart' Class: Salsa20 extends Object implements Type: Algorithm {

Function 'Salsa20.': constructor. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000002664

}

Function 'encrypt':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000185590

}

Function '_buildParams@132180997':. String: null {

Code Offset: _kDartIsolateSnapshotInstructions + 0x0000000000188064

}

}

Library:'package:encrypt/encrypt.dart' Class: Algorithm extends Object {

}

Unboxing through Hooking

main.dart 
===========================================================

main() = sub_3bb8e0 [Widgets and Function Calls]
compare() = sub_2f8954 [comparing s1 & s2]
encrypt() = sub_2f5c08
prepare()
= sub_2f54c0
build()
= sub_2f5268

encrypt.dart [Encrypter]
===========================================================

encryptBytes() = sub_2f5d34
encrypt()
= sub_2f8a00

encrypt.dart [Encrypted]
============================================================

Encrypted.fromUtf8() = sub_172e54 [derivate from Salsa20]
Encrypted.fromLength() = sub_172e54 [derivate from Salsa20]
Key.fromLength() = sub_172e54 [derivate from Encrypted.fromLength]
IV.fromUtf8() = sub_172e54 [derivate from Encrypted.fromUtf8]

get:base64() = sub_2f89bc

Salsa20
============================================================

Salsa20 = sub_172e54
encrypt()
= sub_2f5d80
function hookFunc() {
var isolate = 0x00000000001707f0;
// var target = 0x000000000017c240;
var target = 0x0000000000185418; //encrypt
var dumpOffset = isolate + target;

var argBufferSize = 300

var address = Module.findBaseAddress('libapp.so') // libapp.so (Android) or App (IOS)
console.log('\n\nbaseAddress: ' + address.toString())

var codeOffset = address.add(dumpOffset)
console.log('codeOffset: ' + codeOffset.toString())
console.log('')
console.log('Wait..... ')

Interceptor.attach(codeOffset, {
onEnter: function(args) {

console.log('')
console.log('--------------------------------------------|')
console.log('\n Hook Function: ' + dumpOffset);
console.log('')
console.log('--------------------------------------------|')
console.log('')

// for (var argStep = 0; argStep < 20; argStep++) {
// try {
// dumpArgs(argStep, args[argStep], argBufferSize);
// } catch (e) {
// break;
// }

// }
for(let i = 0; i < 8; i++) {
try {
console.log("addr ",i,args[i]);
console.log(hexdump(args[i]));
console.log("Value")
console.log(Memory.readCString(ptr(args[i])));
console.log("Pointer address hexdump")
console.log(hexdump(ptr(args[i])));
} catch (error) {
console.log("fail",i,(args[i]));
}
}

},
onLeave: function(retval) {
console.log('RETURN : ' + retval)
// console.log(hexdump(retval))
// dumpArgs(0, retval, 300);

// for (var argStep = 0; argStep < 50; argStep++) {
// try {
// dumpArgs(argStep, retval[argStep], argBufferSize);
// } catch (e) {

// break;
// }

// }
}
});

}

function dumpArgs(step, address, bufSize) {

var buf = Memory.readByteArray(address, bufSize)

console.log('Argument ' + step + ' address ' + address.toString() + ' ' + 'buffer: ' + bufSize.toString() + '\n\n Value:\n' +hexdump(buf, {
offset: 0,
length: bufSize,
header: false,
ansi: false
}));

console.log("Trying interpret that arg is pointer")
console.log("=====================================")
try{

console.log(Memory.readCString(ptr(address)));
console.log(ptr(address).readCString());
console.log(hexdump(ptr(address)));
}catch(e){
console.log(e);
}


console.log('')
console.log('----------------------------------------------------')
console.log('')
}

setTimeout(hookFunc, 1000)
from Crypto.Cipher import Salsa20
enc = b"cmc2UbeRkpDnZdyfGoiMEtwgf3n9wug4Gd3SB8EouUM4R7c2tBCVJeOmygQqjE5LNy6DmaDRkqEzG0nrkXkYHG77ooISZ23vLqR+LQ=="
key = b"\x00"*32
nonce_iv = b''.join([chr(i).encode() for i in [0x10,0x18,0x5a,0x22,0x7,0x7e,0x62,0x41]])
cip = Salsa20.new(key=key,nonce=nonce_iv)
print(cip.decrypt(base64.b64decode(enc)))

Thoughts

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

Written by Felix Alexander

Penetration Tester, DFIR & Reverse Engineering Enthusiast

No responses yet

Write a response