MASTG-TECH-0097: Engenharia Reversa em Tempo de Execução

A engenharia reversa em tempo de execução (runtime reverse engineering) pode ser vista como a versão dinâmica da engenharia reversa onde você não tem os dados binários em seu computador host. Em vez disso, você os analisa diretamente da memória do aplicativo.

Continuaremos usando o aplicativo iGoat-Swift, abriremos uma sessão com r2frida r2 frida://usb//iGoat-Swift e você pode começar exibindo as informações do binário alvo usando o comando :i:

[0x00000000]> :i
arch                arm
bits                64
os                  darwin
pid                 2166
uid                 501
objc                true
runtime             V8
java                false
cylang              true
pageSize            16384
pointerSize         8
codeSigningPolicy   optional
isDebuggerAttached  false
cwd                 /

Pesquise todos os símbolos de um determinado módulo com :is <lib>, por exemplo :is libboringssl.dylib.

O seguinte faz uma busca case-insensitive (grep) por símbolos incluindo "aes" (~+aes).

[0x00000000]> :is libboringssl.dylib~+aes
0x1863d6ed8 s EVP_aes_128_cbc
0x1863d6ee4 s EVP_aes_192_cbc
0x1863d6ef0 s EVP_aes_256_cbc
0x1863d6f14 s EVP_has_aes_hardware
0x1863d6f1c s aes_init_key
0x1863d728c s aes_cipher
0x0 u ccaes_cbc_decrypt_mode
0x0 u ccaes_cbc_encrypt_mode
...

Ou você pode preferir analisar as importações/exportações. Por exemplo:

  • Liste todas as importações do binário principal: :ii iGoat-Swift.
  • Liste as exportações da biblioteca libc++.1.dylib: :iE /usr/lib/libc++.1.dylib.

Para binários grandes, é recomendado redirecionar a saída para o programa interno less acrescentando ~.., ou seja, :ii iGoat-Swift~.. (caso contrário, para este binário, você obteria quase 5000 linhas impressas no seu terminal).

A próxima coisa que você pode querer analisar são as classes:

[0x00000000]> :ic~+passcode
PSPasscodeField
_UITextFieldPasscodeCutoutBackground
UIPasscodeField
PasscodeFieldCell
...

Liste os campos de uma classe:

[0x19687256c]> :ic UIPasscodeField
0x000000018eec6680 - becomeFirstResponder
0x000000018eec5d78 - appendString:
0x000000018eec6650 - canBecomeFirstResponder
0x000000018eec6700 - isFirstResponder
0x000000018eec6a60 - hitTest:forEvent:
0x000000018eec5384 - setKeyboardType:
0x000000018eec5c8c - setStringValue:
0x000000018eec5c64 - stringValue
...

Imagine que você está interessado em 0x000000018eec5c8c - setStringValue:. Você pode navegar até esse endereço com s 0x000000018eec5c8c, analisar essa função com af e imprimir 10 linhas de sua desmontagem pd 10:

[0x18eec5c8c]> pd 10 (fcn) fcn.18eec5c8c 35   fcn.18eec5c8c (int32_t arg1, int32_t arg3); bp: 0 (vars 0, args 0) sp: 0 (vars 0, args 0) rg: 2 (vars 0, args 2)           0x18eec5c8c      f657bd         not byte [rdi - 0x43]      ; arg1
│           0x18eec5c8f      a9f44f01a9     test eax, 0xa9014ff4
│           0x18eec5c94      fd             std
│       ╭─< 0x18eec5c95      7b02           jnp 0x18eec5c99
│          0x18eec5c97      a9fd830091     test eax, 0x910083fd
│           0x18eec5c9c      f30300         add eax, dword [rax]           0x18eec5c9f      aa             stosb byte [rdi], al
│       ╭─< 0x18eec5ca0      e003           loopne 0x18eec5ca5
│          0x18eec5ca2      02aa9b494197   add ch, byte [rdx - 0x68beb665] ; arg3
╰           0x18eec5ca8      f4             hlt

Finalmente, em vez de fazer uma busca completa por strings na memória, você pode querer recuperar as strings de um determinado binário e filtrá-las, como faria offline com o radare2. Para isso, você precisa encontrar o binário, navegar até ele e executar o comando :iz.

É recomendado aplicar um filtro com uma palavra-chave ~<keyword>/~+<keyword> para minimizar a saída no terminal. Se quiser apenas explorar todos os resultados, você também pode redirecioná-los para o less interno com :iz~...

[0x00000000]> :il~iGoa
0x00000001006b8000 iGoat-Swift
[0x00000000]> s 0x00000001006b8000
[0x1006b8000]> :iz
Reading 2.390625MB ...
Do you want to print 8568 lines? (y/N) N
[0x1006b8000]> :iz~+hill
Reading 2.390625MB ...
[0x1006b8000]> :iz~+pass
Reading 2.390625MB ...
0x00000001006b93ed  "passwordTextField"
0x00000001006bb11a  "11iGoat_Swift20KeychainPasswordItemV0C5ErrorO"
0x00000001006bb164  "unexpectedPasswordData"
0x00000001006d3f62  "Error reading password from keychain - "
0x00000001006d40f2  "Incorrect Password"
0x00000001006d4112  "Enter the correct password"
0x00000001006d4632  "T@"UITextField",N,W,VpasswordField"
0x00000001006d46f2  "CREATE TABLE IF NOT EXISTS creds (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT, password TEXT);"
0x00000001006d4792  "INSERT INTO creds(username, password) VALUES(?, ?)"

Para saber mais, consulte o wiki do r2frida.