-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support to log the secrets from BoringSSL when it is used in the …
…android mono runtime
- Loading branch information
1 parent
3c53f66
commit 74b319b
Showing
8 changed files
with
514 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
|
||
import { Mono_BTLS } from "../ssl_lib/monobtls.js"; | ||
import { socket_library } from "./android_agent.js"; | ||
import {PatternBasedHooking, get_CPU_specific_pattern } from "../shared/pattern_based_hooking.js"; | ||
import { patterns, isPatternReplaced } from "../ssl_log.js" | ||
import { devlog, devlog_error } from "../util/log.js"; | ||
|
||
|
||
export class Mono_BTLS_Android extends Mono_BTLS { | ||
private default_pattern: { [arch: string]: { primary: string; fallback: string } }; | ||
|
||
constructor(public moduleName:string, public socket_library:String, is_base_hook: boolean){ | ||
super(moduleName,socket_library,is_base_hook); | ||
|
||
this.default_pattern = { | ||
"x64": { | ||
primary: "55 41 57 41 56 41 54 53 49 89 D4 49 89 F6 48 89 FB E8 5A F8 FF FF", // Primary pattern | ||
fallback: "55 41 57 41 56 41 55 41 54 53 48 83 EC 38 48 8B 47 68 48 83 B8 10 02 00 00 00 0F 84 19 01 00 00" // Fallback pattern | ||
}, | ||
"x86": { | ||
primary: "55 89 E5 53 57 56 83 E4 F0 83 EC 10 E8 00 00 00 00", // Primary pattern | ||
fallback: "55 53 57 56 83 EC 4C E8 00 00 00 00 5B 81 C3 A9 CB 13 00 8B 44 24 60 8B 40 34" // Fallback pattern | ||
}, | ||
"arm64": { | ||
primary: "F6 57 BD A9 F4 4F 01 A9 FD 7B 02 A9 FD 83 00 91 F3 03 02 AA F4 03 01 AA F5 03 00 AA 1F FE FF 97", // Primary pattern | ||
fallback: "FF 83 01 D1 F6 1B 00 F9 F5 53 04 A9 F3 7B 05 A9 08 34 40 F9 08 09 41 F9 68 07 00 B4" // Fallback pattern | ||
}, | ||
"arm": { | ||
primary: "F0 B5 03 AF 4D F8 04 8D 14 46 0D 46 06 46 FF F7 5F FD", // Primary pattern | ||
fallback: "2D E9 F0 41 86 B0 04 46 40 6B D0 F8 30 01 00 28 53 D0" // Fallback pattern | ||
} | ||
}; | ||
} | ||
|
||
|
||
|
||
|
||
install_key_extraction_hook(){ | ||
const flutterModule = Process.findModuleByName(this.module_name); | ||
const hooker = new PatternBasedHooking(flutterModule); | ||
|
||
if (isPatternReplaced()){ | ||
devlog("Hooking Libmono functions by patterns from JSON file"); | ||
hooker.hook_DumpKeys(this.module_name,"libmono-btls-shared.so",patterns,(args: any[]) => { | ||
this.dumpKeys(args[1], args[0], args[2]); // Unpack args into dumpKeys | ||
}); | ||
}else{ | ||
// This are the default patterns for hooking ssl_log_secret in BoringSSL inside Libmono | ||
hooker.hookModuleByPattern( | ||
get_CPU_specific_pattern(this.default_pattern), | ||
(args) => { | ||
this.dumpKeys(args[1], args[0], args[2]); // Hook args passed to dumpKeys | ||
} | ||
); | ||
} | ||
|
||
} | ||
|
||
execute_hooks(){ | ||
this.install_key_extraction_hook(); | ||
} | ||
|
||
} | ||
|
||
|
||
export function mono_btls_execute(moduleName:string, is_base_hook: boolean){ | ||
var mono_btls = new Mono_BTLS_Android(moduleName,socket_library,is_base_hook); | ||
try { | ||
mono_btls.execute_hooks(); | ||
}catch(error_msg){ | ||
devlog_error(`mono_btls_execute error: ${error_msg}`) | ||
} | ||
|
||
if (is_base_hook) { | ||
try { | ||
const init_addresses = mono_btls.addresses[moduleName]; | ||
// ensure that we only add it to global when we are not | ||
if (Object.keys(init_addresses).length > 0) { | ||
(global as any).init_addresses[moduleName] = init_addresses; | ||
} | ||
}catch(error_msg){ | ||
devlog_error(`mono_btls_execute base-hook error: ${error_msg}`) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { get_hex_string_from_byte_array, readAddresses } from "../shared/shared_functions.js"; | ||
import { devlog } from "../util/log.js"; | ||
|
||
|
||
|
||
|
||
export class Mono_BTLS { | ||
|
||
|
||
// global variables | ||
library_method_mapping: { [key: string]: Array<string> } = {}; | ||
addresses: { [libraryName: string]: { [functionName: string]: NativePointer } }; | ||
module_name: string; | ||
is_base_hook: boolean; | ||
|
||
|
||
constructor(public moduleName:string, public socket_library:String,is_base_hook: boolean ,public passed_library_method_mapping?: { [key: string]: Array<string> } ){ | ||
this.module_name = moduleName; | ||
this.is_base_hook = is_base_hook; | ||
|
||
if(typeof passed_library_method_mapping !== 'undefined'){ | ||
this.library_method_mapping = passed_library_method_mapping; | ||
}else{ | ||
this.library_method_mapping[`*${socket_library}*`] = ["getpeername", "getsockname", "ntohs", "ntohl"] | ||
} | ||
|
||
this.addresses = readAddresses(moduleName,this.library_method_mapping); | ||
} | ||
|
||
get_client_random(s3_ptr: NativePointer, SSL3_RANDOM_SIZE: number): string { | ||
if (!s3_ptr.isNull()) { | ||
const client_random_ptr: NativePointer = s3_ptr.add(0x30); // Offset in s3 struct | ||
//@ts-ignore | ||
const client_random = Memory.readByteArray(client_random_ptr, SSL3_RANDOM_SIZE); | ||
|
||
// Convert the byte array to a hex string | ||
const hexClientRandom = get_hex_string_from_byte_array(new Uint8Array(client_random as ArrayBuffer)); | ||
|
||
return hexClientRandom; | ||
} else { | ||
devlog("[Error] s3 pointer is NULL"); | ||
return ""; | ||
} | ||
} | ||
|
||
get_client_random_from_ssl_struct(ssl_st_ptr: NativePointer): string { | ||
const SSL3_RANDOM_SIZE = 32; | ||
let offset_s3: number; | ||
|
||
switch (Process.arch) { | ||
case 'x64': | ||
offset_s3 = 0x30; | ||
break; | ||
case 'arm64': | ||
offset_s3 = 0x30; | ||
break; | ||
case 'ia32': | ||
offset_s3 = 0x2C; | ||
break; | ||
case 'arm': | ||
offset_s3 = 0x2C; | ||
break; | ||
default: | ||
devlog("[Error] Unsupported architecture"); | ||
return ""; | ||
} | ||
|
||
const s3_ptr = ssl_st_ptr.add(offset_s3).readPointer(); | ||
return this.get_client_random(s3_ptr, SSL3_RANDOM_SIZE); | ||
} | ||
|
||
|
||
dumpKeys(labelPtr: NativePointer, sslStructPtr: NativePointer, keyPtr: NativePointer): void { | ||
const KEY_LENGTH = 32; // Assuming key length is 32 bytes | ||
|
||
let labelStr = ''; | ||
let client_random = ''; | ||
let secret_key = ''; | ||
|
||
// Read the label (the label pointer might contain a C string) | ||
if (!labelPtr.isNull()) { | ||
labelStr = labelPtr.readCString() ?? ''; // Read label as a C string | ||
//devlog(`Label: ${labelStr}`); | ||
} else { | ||
devlog("[Error] Argument 'labelPtr' is NULL"); | ||
} | ||
|
||
// Extract client_random from the SSL structure | ||
if (!sslStructPtr.isNull()) { | ||
client_random = this.get_client_random_from_ssl_struct(sslStructPtr) | ||
}else { | ||
devlog("[Error] Argument 'sslStructPtr' is NULL"); | ||
} | ||
|
||
if (!keyPtr.isNull()) { | ||
//@ts-ignore | ||
const keyData = Memory.readByteArray(keyPtr, KEY_LENGTH); // Read the key data (KEY_LENGTH bytes) | ||
|
||
// Convert the byte array to a string of hex values | ||
const hexKey = get_hex_string_from_byte_array(keyData); | ||
|
||
secret_key = hexKey; | ||
} else { | ||
devlog("[Error] Argument 'key' is NULL"); | ||
} | ||
|
||
//devlog("invoking ssl_log_secret() from BoringSSL statically linked into Mono BTLS"); | ||
var message: { [key: string]: string | number | null } = {} | ||
message["contentType"] = "keylog" | ||
message["keylog"] = labelStr+" "+client_random+" "+secret_key; | ||
send(message) | ||
} | ||
|
||
install_plaintext_read_hook(){ | ||
// TBD | ||
} | ||
|
||
install_plaintext_write_hook(){ | ||
// TBD | ||
} | ||
|
||
install_key_extraction_hook(){ | ||
// needs to be setup for the specific plattform | ||
} | ||
} |
Oops, something went wrong.