MASTG-TOOL-0046: Cycript

Deprecated Tool

This tool is deprecated and should not be used anymore.

Reason: Cycript is no longer actively maintained and fails on modern iOS versions. It last saw meaningful updates between 2009 and 2013. Key components like cynject broke on iOS 12 around 2019 due to changes in Cydia Substrate and have not been fixed. Frida offers broader compatibility, active support, and more powerful dynamic instrumentation capabilities.

Use instead:

Cycript é uma linguagem de script desenvolvida por Jay Freeman (também conhecido como Saurik). Ele injeta uma máquina virtual JavaScriptCore em um processo em execução. Usando o console interativo do Cycript, os usuários podem manipular o processo com uma sintaxe híbrida de Objective-C++ e JavaScript. O acesso e a instanciação de classes Objective-C dentro de um processo em execução são suportados. O Cycript pode ser injetado em um processo em execução, semelhante a um debugger, usando o Cydia Substrate, que é o framework padrão para desenvolver patches em tempo de execução Cydia, conhecidos como Cydia Substrate Extensions no iOS. Ele inclui o Cynject, uma ferramenta que fornece suporte à injeção de código para o Cycript.

Para instalar o Cycript, primeiro faça o download, descompacte e instale o SDK.

# no iPhone
$ wget https://cydia.saurik.com/api/latest/3 -O cycript.zip && unzip cycript.zip
$ sudo cp -a Cycript.lib/*.dylib /usr/lib
$ sudo cp -a Cycript.lib/cycript-apl /usr/bin/cycript

Para iniciar o shell interativo do Cycript, execute ./cycript ou cycript se o Cycript estiver no seu PATH.

$ cycript
cy#

Para injetar em um processo em execução, primeiro precisamos encontrar o ID do processo (PID). Execute o aplicativo e certifique-se de que ele esteja em primeiro plano. Executar cycript -p <PID> injeta o Cycript no processo. Para ilustrar, vamos injetar no SpringBoard (que está sempre em execução).

$ ps -ef | grep SpringBoard
501 78 1 0 0:00.00 ?? 0:10.57 /System/Library/CoreServices/SpringBoard.app/SpringBoard
$ ./cycript -p 78
cy#

Uma das primeiras coisas que você pode tentar é obter a instância do aplicativo (UIApplication), você pode usar a sintaxe Objective-C:

cy# [UIApplication sharedApplication]
cy# var a = [UIApplication sharedApplication]

Use essa variável agora para obter a classe delegate do aplicativo:

cy# a.delegate

Vamos tentar acionar uma mensagem de alerta no SpringBoard com o Cycript.

cy# alertView = [[UIAlertView alloc] initWithTitle:@"OWASP MASTG" message:@"Mobile Application Security Testing Guide"  delegate:nil cancelButtonitle:@"OK" otherButtonTitles:nil]
#"<UIAlertView: 0x1645c550; frame = (0 0; 0 0); layer = <CALayer: 0x164df160>>"
cy# [alertView show]
cy# [alertView release]

Encontre o diretório de documentos do aplicativo com o Cycript:

cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
#"file:///var/mobile/Containers/Data/Application/A8AE15EE-DC8B-4F1C-91A5-1FED35212DF/Documents/"

O comando [[UIApp keyWindow] recursiveDescription].toString() retorna a hierarquia de visualizações da keyWindow. A descrição de cada subvisualização e sub-subvisualização da keyWindow é exibida. O espaço de indentação reflete os relacionamentos entre as visualizações. Por exemplo, UILabel, UITextField e UIButton são subvisualizações de UIView.

cy# [[UIApp keyWindow] recursiveDescription].toString()
`<UIWindow: 0x16e82190; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x16e80ac0>; layer = <UIWindowLayer: 0x16e63ce0>>
  | <UIView: 0x16e935f0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x16e93680>>
  |    | <UILabel: 0x16e8f840; frame = (0 40; 82 20.5); text = 'i am groot!'; hidden = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16e8f920>>
  |    | <UILabel: 0x16e8e030; frame = (0 110.5; 320 20.5); text = 'A Secret Is Found In The ...'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16e8e290>>
  |    | <UITextField: 0x16e8fbd0; frame = (8 141; 304 30); text = ''; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x16e94550>; layer = <CALayer: 0x16e8fea0>>
  |    |    | <_UITextFieldRoundedRectBackgroundViewNeue: 0x16e92770; frame = (0 0; 304 30); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x16e92990>>
  |    | <UIButton: 0x16d901e0; frame = (8 191; 304 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x16d90490>>
  |    |    | <UIButtonLabel: 0x16e72b70; frame = (133 6; 38 18); text = 'Verify'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16e974b0>>
  |    | <_UILayoutGuide: 0x16d92a00; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x16e936b0>>
  |    | <_UILayoutGuide: 0x16d92c10; frame = (0 568; 0 0); hidden = YES; layer = <CALayer: 0x16d92cb0>>`

Você também pode usar as funções integradas do Cycript, como choose, que pesquisa o heap por instâncias da classe Objective-C fornecida:

cy# choose(SBIconModel)
[#"<SBIconModel: 0x1590c8430>"]

Saiba mais no Manual do Cycript.