IDA Plugin for ease the reversing of iOS' usermode and kernelcache.
Project description
IDA iOS Helper
A plugin for IDA Pro 9.0+ to help with iOS code analysis.
Supported features
- KernelCache
- Calls to
OSBaseClass::safeMetaCastapply type info on the result. - Calls to
OSObject_typed_operator_newapply type info on the result. - When the keyboard is on a virtual call (
cls->vcall()), Shift+X will show a dialog with all the possible implementations of the virtual method. It requires vtable symbols to be present. - When in a C++ method named Class::func, Ctrl+T will change the first argument to
Class* this. Also works for Obj-C instance methods. - Name globals from
OSSymbol::fromConst*calls, locals fromget/setPropertycalls, ... - Rename and type all global kalloc_type_view. Use their signature to mark fields as pointers for the actual types.
- Create a struct from a kalloc_type_view.
- Calls to
- Objective-C
- Hide memory management
functions -
objc_retain,objc_release,objc_autorelease,objc_retainAutoreleasedReturnValue.- Optimize
_objc_storeStrongto an assignment.
- Optimize
- collapse
__os_log_implcalls. - Hide selectors and static classes from Objective-c calls.
- When in Obj-C method, Ctrl+4 will show xrefs to the selector.
- Hide memory management
functions -
- Swift
- Add swift types declarations to the IDA type system.
- Detect stack swift string and add a syntactic sugar for them.
- Common
- Remove
__breakcalls. - collapse blocks initializers and detect
__blockvariables (use Alt+Shift+S to trigger detection). - Use
Ctrl+Sto jump to function by a string constant found in the code - Transform ranged conditions to a more readable form.
- Try to detect outline functions and mark them as such.
- Use
Ctrl+Shift+Xto find xrefs to a field inside a segment. This will decompile the whole segment and then search for the field.
- Remove
Installation
- Install this package using your IDA's python pip:
pip install ida-ios-helper - copy
ida-plugin.jsonandida_plugin_stub.pyto your IDA's plugins folder:~/.idapro/plugins/ida-ios-helper. - Restart IDA.
Examples
Solve condition constraints
Before:
if ( valueLength - 21 <= 0xFFFFFFFFFFFFFFEFLL )
{
...
}
After:
if ( 4 < valueLength || valueLength < 21 )
{
...
}
Remove __break
Before:
if ( ((v6 ^ (2 * v6)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
After: removed.
Hide selectors of Obj-C calls
Before:
-[NSFileManager removeItemAtPath:error:](
+[NSFileManager defaultManager](&OBJC_CLASS___NSFileManager, "defaultManager"),
"removeItemAtPath:error:",
+[NSString stringWithUTF8String:](&OBJC_CLASS___NSString, "stringWithUTF8String:", *(_QWORD *)&buf[v5]),
0LL);
After:
-[NSFileManager removeItemAtPath:error:](
+[NSFileManager defaultManager](),
+[NSString stringWithUTF8String:](*(_QWORD *)&buf[v5]),
0LL);
Block initializers
Before:
v10 = 0LL;
v15 = &v10;
v16 = 0x2000000000LL;
v17 = 0;
if ( a1 )
{
x0_8 = *(NSObject **)(a1 + 16);
v13.isa = _NSConcreteStackBlock;
*(_QWORD *)&v13.flags = 0x40000000LL;
v13.invoke = func_name_block_invoke;
v13.descriptor = &stru_100211F48;
v13.lvar3 = a1;
v13.lvar4 = a2;
v13.lvar1 = a3;
v13.lvar2 = &v10;
dispatch_sync(queue: x0_8, block: &v13);
v11 = *((_BYTE *)v15 + 24);
}
else
{
v11 = 0;
}
_Block_object_dispose(&v10, 8);
return v11 & 1;
After:
v10 = _byref_block_arg_init(0);
v10.value = 0;
if ( a1 )
{
v6 = *(NSObject **)(a1 + 16);
v9 = _stack_block_init(0x40000000, &stru_100211F48, func_name_block_invoke);
v9.lvar3 = a1;
v9.lvar4 = a2;
v9.lvar1 = a3;
v9.lvar2 = &v10;
dispatch_sync(queue: v6, block: &v9);
value = v10.forwarding->value;
}
else
{
value = 0;
}
return value & 1;
Collapse os_log
Before:
v9 = gLogObjects;
v10 = gNumLogObjects;
if ( gLogObjects && gNumLogObjects >= 46 )
{
v11 = *(NSObject **)(gLogObjects + 360);
}
else
{
v11 = (NSObject *)&_os_log_default;
if ( ((v6 ^ (2 * v6)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
if ( os_log_type_enabled(oslog: (os_log_t)&_os_log_default, type: OS_LOG_TYPE_ERROR) )
{
*(_DWORD *)buf = 134218240;
*(_QWORD *)v54 = v9;
*(_WORD *)&v54[8] = 1024;
*(_DWORD *)&v54[10] = v10;
if ( ((v6 ^ (2 * v6)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
_os_log_error_impl(
dso: (void *)&_mh_execute_header,
log: (os_log_t)&_os_log_default,
type: OS_LOG_TYPE_ERROR,
format: "Make sure you have called init_logging()!\ngLogObjects: %p, gNumLogObjects: %d",
buf: buf,
size: 0x12u);
}
}
if ( ((v6 ^ (2 * v6)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
if ( os_log_type_enabled(oslog: v11, type: OS_LOG_TYPE_INFO) )
{
if ( a1 )
v12 = *(_QWORD *)(a1 + 8);
else
v12 = 0LL;
*(_DWORD *)buf = 138412290;
*(_QWORD *)v54 = v12;
if ( ((v6 ^ (2 * v6)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
_os_log_impl(
dso: (void *)&_mh_execute_header,
log: v11,
type: OS_LOG_TYPE_INFO,
format: "Random log %@",
buf: buf,
size: 0xCu);
}
after:
if ( oslog_info_enabled() )
{
if ( a1 )
v4 = *(_QWORD *)(a1 + 8);
else
v4 = 0LL;
oslog_info("Random log %@", v4);
}
Automatic casts with OSBaseClass::safeMetaCast
Before:
OSObject *v5;
v5 = OSBaseClass::safeMetaCast(a2, &IOThunderboltController::metaClass);
After:
IOThunderboltController *v5;
v5 = OSDynamicCast<IOThunderboltController>(a2);
Automatic typing for OSObject_typed_operator_new
Run Edit->Plugins->iOSHelper->Locate all kalloc_type_view before.
Before:
IOAccessoryPowerSourceItemUSB_TypeC_Current *sub_FFFFFFF009B2AA14()
{
OSObject *v0; // x19
v0 = (OSObject *)OSObject_typed_operator_new(&UNK_FFFFFFF007DBC480, size: 0x38uLL);
OSObject::OSObject(this: v0, &IOAccessoryPowerSourceItemUSB_TypeC_Current::gMetaclass)->__vftable = (OSObject_vtbl *)off_FFFFFFF007D941B0;
OSMetaClass::instanceConstructed(this: &IOAccessoryPowerSourceItemUSB_TypeC_Current::gMetaclass);
return (IOAccessoryPowerSourceItemUSB_TypeC_Current *)v0;
}
After:
IOAccessoryPowerSourceItemUSB_TypeC_Current *sub_FFFFFFF009B2AA14()
{
IOAccessoryPowerSourceItemUSB_TypeC_Current *v0; // x19
v0 = OSObjectTypeAlloc<IOAccessoryPowerSourceItemUSB_TypeC_Current>(0x38uLL);
OSObject::OSObject(this: v0, &IOAccessoryPowerSourceItemUSB_TypeC_Current::gMetaclass)->__vftable = (OSObject_vtbl *)off_FFFFFFF007D941B0;
OSMetaClass::instanceConstructed(this: &IOAccessoryPowerSourceItemUSB_TypeC_Current::gMetaclass);
return v0;
}
Jump to virtual call
Use Shift+X on a virtual call to jump.
Xrefs to selector
Use Ctrl+4 inside an Objective-C method to list xrefs to its selector.
Rename function by argument of logging function
Given that the code contains calls like:
log("func_name", ....);
You could use rename_function_by_arg to mass rename all functions that contain such calls.
rename_function_by_arg(func_name="log", arg_index=0, prefix="_", force_name_change=False)
This will run on all the functions that call the log function, and rename them to the first argument of the call.
Call the plugin from python
import idaapi
# Call global analysis
idaapi.load_and_run_plugin("iOS Helper", 1)
# Call local analysis
def write_ea_arg(ea: int):
n = idaapi.netnode()
n.create("$ idaioshelper")
n.altset(1, ea, "R")
write_ea_arg(func_ea)
idaapi.load_and_run_plugin("iOS Helper", 2)
Development
In order to have autocomplete while developing, you need to add IDA's include folder ( $IDA_INSTALLATION/python/3 ) to
your IDE.
- on Visual Studio code you can add the folder to the analyzer's extra paths in the
settings.jsonfile:
{
"python.analysis.extraPaths": [
"$IDA_INSTALLATION\\python\\3"
]
}
- on PyCharm you can add the folder to the interpreter's paths in the project settings.
Alternatively, you can create
idapython.pthin$VENV_FOLDER/Lib/site-packagesand add the path to it.
Inside IDA, you can use ioshelper.reload() to reload the plugin during development.
If you create file name DEBUG inside src/, then you can use F2 to reload the
plugin.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ida_ios_helper-1.0.20.tar.gz.
File metadata
- Download URL: ida_ios_helper-1.0.20.tar.gz
- Upload date:
- Size: 867.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ea7ac2ea4f491792d1b5904ccc16b324567b22d755c20986ce3dba4a1016104
|
|
| MD5 |
c41d2ec0bf6984b1707331190a72b756
|
|
| BLAKE2b-256 |
bed386c6e5a3a6bb957ef87b32a456aaab66c4e17240503e9c0af78300edf99f
|
Provenance
The following attestation bundles were made for ida_ios_helper-1.0.20.tar.gz:
Publisher:
pypi.yaml on yoavst/ida-ios-helper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ida_ios_helper-1.0.20.tar.gz -
Subject digest:
6ea7ac2ea4f491792d1b5904ccc16b324567b22d755c20986ce3dba4a1016104 - Sigstore transparency entry: 969536907
- Sigstore integration time:
-
Permalink:
yoavst/ida-ios-helper@2a35afe4d64f4e0f521be7d40635a6295166b5a3 -
Branch / Tag:
refs/tags/1.0.20 - Owner: https://github.com/yoavst
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@2a35afe4d64f4e0f521be7d40635a6295166b5a3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ida_ios_helper-1.0.20-py3-none-any.whl.
File metadata
- Download URL: ida_ios_helper-1.0.20-py3-none-any.whl
- Upload date:
- Size: 95.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db9e93c7d9769ea62b18886916ec164c604f4a0d9a6e1350bf48f7fb0e9d4efb
|
|
| MD5 |
f0f4e4fa620506e8d6a12af7beeed282
|
|
| BLAKE2b-256 |
dac5832d79f8f58f1f10486302a14a81bf83b773c41eeab3a258966d57762552
|
Provenance
The following attestation bundles were made for ida_ios_helper-1.0.20-py3-none-any.whl:
Publisher:
pypi.yaml on yoavst/ida-ios-helper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ida_ios_helper-1.0.20-py3-none-any.whl -
Subject digest:
db9e93c7d9769ea62b18886916ec164c604f4a0d9a6e1350bf48f7fb0e9d4efb - Sigstore transparency entry: 969536913
- Sigstore integration time:
-
Permalink:
yoavst/ida-ios-helper@2a35afe4d64f4e0f521be7d40635a6295166b5a3 -
Branch / Tag:
refs/tags/1.0.20 - Owner: https://github.com/yoavst
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@2a35afe4d64f4e0f521be7d40635a6295166b5a3 -
Trigger Event:
push
-
Statement type: