jailbreak env
ssh
The first connection will ask for your confirmation, you need to type yes
.
The public key information will be saved in C:\Users\Administrator\.ssh\known_hosts
.
When prompted with an “man-in-the-middle attack” warning, you can resolve it by deleting the public key inside.
Passwordless Login
Generate a public-private key pair using
ssh-keygen
.Save path:
C:\Users\Administrator/.ssh/id_rsa
(private key)C:\Users\Administrator/.ssh/id_rsa.pub
(public key)
Copy the public key to the corresponding directory on the mobile device:
scp C:\Users\Administrator/.ssh/id_rsa.pub root@ip:/tmp
Append the public key’s content from
/tmp/id_rsa.pub
to.ssh/authorized_keys
:- Connect to the server:
ssh root@192.168.1.4
- Create the
.ssh
directory if it doesn’t exist:mkdir .ssh
- Append the key:
cat /tmp/id_rsa.pub >> .ssh/authorized_keys
- Connect to the server:
To cancel passwordless login, simply delete the
authorized_keys
file on the mobile device.
Passwordless login essentially uses the computer’s public key as a password to log in, which is why a public-private key pair must be generated first.
https://dkxuanye.cn/?cat=116 good toturials :)
WinRa1n 2.0 is a good tool :)
or use 爱斯助手 the usb ones method
frida
frida https://frida.re/docs/ios/#with-jailbreak
you don’t have to connect with computer via usb cab
windows can’t connect with ios via usb… it seems like that it’s drive should be changed…
but we can solve this problem by wireless remote connect
0x00 备注
我们经常用旧的手机来做越狱和调试, 这个usb连接真的是差强人意, 老是关键时刻掉线
0x01 iPhone ssh运行:
frida-server -l 0.0.0.0
0x02 MacOS 中运行 :
frida-ps -H 192.168.111.120
0x03 执行frida操作
frida-trace -H 192.168.1.3:1337 -i "open*"
记得加上-H IP
# listen on 127.0.0.1:27042 (the default)
$ frida-server
# listen on all interfaces
$ frida-server -l 0.0.0.0
# listen on a specific interface
$ frida-server -l 192.168.1.3
# listen on a specific interface and port
$ frida-server -l 192.168.1.3:1337
# connect to specific IP
$ frida-trace -H 192.168.1.3 -i "open*"
# connect to specific IP/port
$ frida-trace -H 192.168.1.3:1337 -i "open*"
cyz1nappleID
install shit
framework like lsp: theos
install a specific version of frida
https://github.com/frida/frida/releases?q=14.2.18&expanded=true. choose frida_14.2.18_iphoneos-arm.deb
use scp
command to move this file from pc to ipone
cd /tmp
dpkg -i frida_xxxxx
ps aux |grep frida
on your PC, install corresponding frida and frida-tools https://github.com/thelicato/frida-compatibility-matrix
install objection
recommend version:
pip install frida==14.2.18
pip install frida-tools==9.2.5
pip install objection==1.11.0 (latest)
install trollstore
https://ios.cfw.guide/installing-trollstore/
Ch1ne5e user remember to open VPN, it need to download kernel.
Charles
- download a certificate on ios
charlesproxy.com/getssl
chls.pro/ssl
- click click in iphone
env detection
sometimes, an application can bypass system proxy, so we can use a VPN to force it to go through our proxy. Here we use Shadowrocket
open charles to see the port and IP
open shadowrocket
, type Socks5
server 192.168.1.6
port8889
. Change Global Routing to ‘Proxy’2
proxy
method 1: hook
method 2:
this is a proxy detection function
see imp
, two posibility: 1. import from system 2. import from a dynamic library. heres its hook script, return 0
var _imports = Process.findModuleByName("tredian").enumerateImports();
var _CFNetworkCopySystemProxySettings = null;
for (var i = 0; i < _imports.length; i++) {
if (_imports[i].name.indexOf("CFNetworkCopySystemProxySettings") != -1) {
console.log(_imports[i].name, _imports[i].address);
_CFNetworkCopySystemProxySettings = _imports[i].address;
}
}
if (_CFNetworkCopySystemProxySettings) {
Interceptor.attach(_CFNetworkCopySystemProxySettings, {
onEnter: function(agrgs) {
// InvocationArguments
},
onLeave: function(retval) {
// InvocationReturnValue
console.log("retval: ", ObjC.Object(retval));
retval.replace(0);
}
});
}
// frida-ps -Uai
// frida -U -f maihan.tredian -l hook.js
in a normal environment, _ _SCOPED _ _
only has en0
, but when you open a VPN, utun3 was added.
off-standard port.
weex
once launching a VPN, the app can’t work well. notice that its port isn’t normal, so add this port to Ports
find the place that seems like the place where it sent a post. it called weex
id __cdecl -[WXStreamModule _buildRequestWithOptions:callbackRsp:](WXStreamModule *self, SEL a2, id a3, id a4)
{
id v6; // x27
id v7; // x28
void *v8; // x0
id v9; // x23
void *v10; // x24
void *v11; // x0
id v12; // x21
void *v13; // x0
id v14; // x25
void *v15; // x0
id v16; // x26
void *v17; // x0
id v18; // x19
id v19; // x27
id v20; // x22
__int64 v21; // x28
void *v22; // x0
id v23; // x21
void *v24; // x0
id v25; // x22
void *v26; // x0
id v27; // x22
id v28; // x26
void *v29; // x0
id v30; // x21
void *v31; // x0
id v32; // x21
void *v33; // x0
id v34; // x0
void *v35; // x23
id v36; // x24
char v37; // w25
void *v38; // x0
id v39; // x22
void *v40; // x0
id v41; // x23
double v42; // d0
void *v43; // x0
id v44; // x23
void *v45; // x0
id v46; // x22
void *v47; // x0
__CFString *v48; // x19
void *v49; // x0
id v50; // x23
void *v51; // x0
id v52; // x25
void *v53; // x0
id v54; // x25
void *v55; // x0
id v56; // x25
float v57; // s0
void *v58; // x0
id v59; // x25
void *v60; // x0
id v61; // x25
__int64 v62; // x0
__int64 v63; // x27
__int64 v64; // x21
__int64 i; // x19
void *v66; // x0
void *v67; // x0
id v68; // x24
void *v69; // x0
id v70; // x23
void *v71; // x0
id v72; // x24
int v73; // w26
void *v74; // x0
id v75; // x0
void *v76; // x27
void *v77; // x0
id v78; // x26
int v79; // w23
void *v80; // x0
id v81; // x24
void *v82; // x0
id v83; // x23
void *v84; // x0
void *v85; // x0
id v86; // x23
int v87; // w24
void *v88; // x0
void *v89; // x0
void *v90; // x0
id v91; // x24
void *v92; // x0
id v93; // x23
void *v94; // x0
id v95; // x23
id v97; // [xsp+170h] [xbp+10h]
void *v98; // [xsp+178h] [xbp+18h]
__CFString *v99; // [xsp+180h] [xbp+20h]
id v100; // [xsp+188h] [xbp+28h]
WXStreamModule *v101; // [xsp+198h] [xbp+38h]
id v102; // [xsp+198h] [xbp+38h]
id v103; // [xsp+1E8h] [xbp+88h]
v6 = objc_retain(a3);
v7 = objc_retain(a4);
v8 = (void *)-[APKKeychainBindings stringForKey:]_0(v6);
v9 = objc_retainAutoreleasedReturnValue(v8);
sub_1014BB4E0(&OBJC_CLASS___NSString);
if ( (sub_1014DE220(v9) & 1) != 0 )
{
v10 = (void *)sub_1014BF280(v9);
v11 = (void *)sub_1014D4FC0(&OBJC_CLASS___WXSDKEngine);
v12 = objc_retainAutoreleasedReturnValue(v11);
v101 = self;
if ( (unsigned int)sub_1014F5DA0() )
{
v13 = (void *)-[DCUniComponent uniInstance]_0(self);
v14 = objc_retainAutoreleasedReturnValue(v13);
v15 = (void *)sub_1014F6B40(v12);
v16 = objc_retainAutoreleasedReturnValue(v15);
v17 = (void *)sub_1014AF780();
v18 = v6;
v19 = objc_retainAutoreleasedReturnValue(v17);
v20 = v7;
v21 = sub_1014BF280(v19);
objc_release(v10);
v22 = v19;
v6 = v18;
objc_release(v22);
objc_release(v16);
objc_release(v14);
v10 = (void *)v21;
v7 = v20;
}
objc_release(v12);
v23 = objc_retain(v10);
objc_release(v9);
if ( !v6 || (unsigned int)sub_1014DD000(&OBJC_CLASS___WXUtility) )
{
v24 = (void *)sub_1014E8EE0(&OBJC_CLASS___NSNumber);
v25 = objc_retainAutoreleasedReturnValue(v24);
sub_10150C640(v7);
objc_release(v25);
v26 = (void *)sub_1014E8E60(&OBJC_CLASS___NSNumber);
v27 = objc_retainAutoreleasedReturnValue(v26);
sub_10150C640(v7);
objc_release(v27);
v28 = 0LL;
LABEL_41:
objc_release(v23);
goto LABEL_42;
}
v33 = (void *)-[DCUniComponent uniInstance]_0(v101);
v34 = objc_retainAutoreleasedReturnValue(v33);
if ( v34 )
{
v35 = v34;
v36 = objc_loadWeakRetained((id *)&v101->weexInstance);
v37 = sub_1014DE1C0();
objc_release(v36);
objc_release(v35);
if ( (v37 & 1) == 0 )
{
v38 = (void *)-[DCUniComponent uniInstance]_0(v101);
v39 = objc_retainAutoreleasedReturnValue(v38);
v40 = (void *)sub_1014ECC80();
v41 = objc_retainAutoreleasedReturnValue(v40);
v42 = sub_1014CECA0();
sub_101504EA0(v41, v42 + 1.0);
objc_release(v41);
objc_release(v39);
}
}
v43 = (void *)sub_1014ABE60(&OBJC_CLASS___NSURL);
v44 = objc_retainAutoreleasedReturnValue(v43);
v45 = (void *)sub_1014F54C0(&OBJC_CLASS___WXResourceRequest);
v46 = objc_retainAutoreleasedReturnValue(v45);
objc_release(v44);
v47 = (void *)-[APKKeychainBindings stringForKey:]_0(v6);
v48 = objc_retainAutoreleasedReturnValue(v47);
if ( (unsigned int)sub_1014DD000(&OBJC_CLASS___WXUtility) )
{
objc_release(v48);
v48 = CFSTR("GET");
}
sub_101505500(v46);
v49 = (void *)-[APKKeychainBindings stringForKey:]_0(v6);
v50 = objc_retainAutoreleasedReturnValue(v49);
sub_1014BB4E0(&OBJC_CLASS___NSString);
if ( (unsigned int)sub_1014DE220(v50) )
{
if ( v50 )
{
v51 = (void *)sub_1014E48C0(v50);
v52 = objc_retainAutoreleasedReturnValue(v51);
sub_10150C640(v7);
objc_release(v52);
}
else
{
sub_10150C640(v7);
}
}
v98 = v50;
v99 = v48;
v100 = v23;
v53 = (void *)sub_101524720(v6);
v54 = objc_retainAutoreleasedReturnValue(v53);
objc_release(v54);
if ( v54 )
{
v55 = (void *)sub_101524720(v6);
v56 = objc_retainAutoreleasedReturnValue(v55);
v57 = sub_1014CDEC0();
sub_101514B20(v46, (float)(v57 / 1000.0));
objc_release(v56);
}
v58 = (void *)sub_1014C1660(&OBJC_CLASS___PTUserAgentUtil);
v59 = objc_retainAutoreleasedReturnValue(v58);
sub_101516420(v46);
objc_release(v59);
v102 = v6;
v60 = (void *)-[APKKeychainBindings stringForKey:]_0(v6);
v61 = objc_retainAutoreleasedReturnValue(v60);
v62 = ((__int64 (*)(void))sub_1014BF720)();
if ( v62 )
{
v63 = v62;
v64 = MEMORY[0];
do
{
for ( i = 0LL; i != v63; ++i )
{
if ( MEMORY[0] != v64 )
objc_enumerationMutation(v61);
v66 = (void *)-[APKKeychainBindings stringForKey:]_0(v61);
v97 = objc_retainAutoreleasedReturnValue(v66);
v67 = (void *)sub_10151D280(&OBJC_CLASS___NSString);
v68 = objc_retainAutoreleasedReturnValue(v67);
objc_release(v97);
sub_101516780(v46);
objc_release(v68);
}
v63 = sub_1014BF720(v61);
}
while ( v63 );
}
v6 = v102;
v69 = (void *)-[APKKeychainBindings stringForKey:]_0(v102);
v70 = objc_retainAutoreleasedReturnValue(v69);
objc_release(v70);
v23 = v100;
if ( v70 )
{
v71 = (void *)-[APKKeychainBindings stringForKey:]_0(v102);
v72 = objc_retainAutoreleasedReturnValue(v71);
sub_1014BB4E0(&OBJC_CLASS___NSString);
v73 = sub_1014DE220(v72);
objc_release(v72);
v74 = (void *)-[APKKeychainBindings stringForKey:]_0(v102);
v75 = objc_retainAutoreleasedReturnValue(v74);
v76 = v75;
if ( v73 )
{
v77 = (void *)sub_1014C20A0(v75);
v78 = objc_retainAutoreleasedReturnValue(v77);
objc_release(v76);
v6 = v102;
if ( !v78 )
{
LABEL_39:
v92 = (void *)sub_1014E8EE0(&OBJC_CLASS___NSNumber);
v93 = objc_retainAutoreleasedReturnValue(v92);
sub_10150C640(v7);
objc_release(v93);
v94 = (void *)sub_1014E8E60(&OBJC_CLASS___NSNumber);
v95 = objc_retainAutoreleasedReturnValue(v94);
sub_10150C640(v7);
objc_release(v95);
v28 = 0LL;
goto LABEL_40;
}
}
else
{
sub_1014BB4E0(&OBJC_CLASS___NSDictionary);
v79 = sub_1014DE220(v76);
objc_release(v76);
if ( v79 )
{
v6 = v102;
v80 = (void *)-[APKKeychainBindings stringForKey:]_0(v102);
v81 = objc_retainAutoreleasedReturnValue(v80);
v82 = (void *)sub_1014AAC20(&OBJC_CLASS___WXUtility);
v83 = objc_retainAutoreleasedReturnValue(v82);
v84 = (void *)((__int64 (*)(void))sub_1014C20A0)();
v78 = objc_retainAutoreleasedReturnValue(v84);
objc_release(v83);
objc_release(v81);
if ( !v78 )
goto LABEL_39;
}
else
{
v6 = v102;
v85 = (void *)-[APKKeychainBindings stringForKey:]_0(v102);
v86 = objc_retainAutoreleasedReturnValue(v85);
sub_1014BB4E0(&OBJC_CLASS___NSData);
v87 = sub_1014DE220(v86);
objc_release(v86);
if ( !v87 )
goto LABEL_39;
v88 = (void *)-[APKKeychainBindings stringForKey:]_0(v102);
v78 = objc_retainAutoreleasedReturnValue(v88);
if ( !v78 )
goto LABEL_39;
}
}
sub_101505460(v46);
objc_release(v78);
}
v89 = (void *)sub_1014E8EE0(&OBJC_CLASS___NSNumber);
v103 = objc_retainAutoreleasedReturnValue(v89);
v90 = (void *)sub_1014C6480(&OBJC_CLASS___NSDictionary);
v91 = objc_retainAutoreleasedReturnValue(v90);
sub_10150C640(v7);
objc_release(v91);
objc_release(v103);
v28 = objc_retain(v46);
LABEL_40:
objc_release(v61);
objc_release(v98);
objc_release(v99);
objc_release(v46);
goto LABEL_41;
}
if ( v7 )
{
v29 = (void *)sub_1014E8EE0(&OBJC_CLASS___NSNumber);
v30 = objc_retainAutoreleasedReturnValue(v29);
sub_10150C640(v7);
objc_release(v30);
v31 = (void *)sub_1014E8E60(&OBJC_CLASS___NSNumber);
v32 = objc_retainAutoreleasedReturnValue(v31);
sub_10150C640(v7);
objc_release(v32);
}
v28 = 0LL;
v23 = v9;
LABEL_42:
objc_release(v23);
objc_release(v7);
objc_release(v6);
return objc_autoreleaseReturnValue(v28);
}
hook it
defineHandler({
onEnter(log, args, state) {
var dic = ObjC.Object(args[2]);
log(`-[WXStreamModule _buildRequestWithOptions:${args[2]} callbackRsp:${args[3]}]`);
log('body', dic.objectForKey_('body'));
},
onLeave(log, retval, state) {
}
});
// frida-trace -U -f com.chinatower.towerEle4 -m "-[WXStreamModule _buildRequestWithOptions:callbackRsp:]"
certificate verification
find the p12
certificate at here
in the next step, find the password
jailbreak
[iOS的越狱检测和反越狱检测剖析][https://www.jianshu.com/p/ab70ded19cf0]
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.avl.com"]])
{
return YES;
}
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]])
{
return YES;
}
defineHandler({
onEnter (log, args, state) {
var URLName = ObjC.Object(args[2]);
if (URLName.containsString_ ("http:") || URLName.containsString_ ("https:") || URLName.containsString_ ("file:")) {
} else {
if (URLName.containsString_ ("://")) {
log("[- NSURL URLWithString:]" + URLName);
args[2] = ObjC.classes.NSString.stringWithString_ ("xxxxxx://");
}
}
},
});
// frida-trace -U -f com.gemd.iting -m "+[NSURL URLWithString:]"
BOOL fileExist(NSString* path)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if([fileManager fileExistsAtPath:path isDirectory:&isDirectory]){
return YES;
}
return NO;
}
BOOL directoryExist(NSString* path)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = YES;
if([fileManager fileExistsAtPath:path isDirectory:&isDirectory]){
return YES;
}
return NO;
}
BOOL canOpen(NSString* path)
{
FILE *file = fopen([path UTF8String], "r");
if(file==nil){
return fileExist(path) || directoryExist(path);
}
fclose(file);
return YES;
}
NSArray* checks = [[NSArray alloc] initWithObjects:@"/Application/Cydia.app",
@"/Library/MobileSubstrate/MobileSubstrate.dylib",
@"/bin/bash",
@"/usr/sbin/sshd",
@"/etc/apt",
@"/usr/bin/ssh",
@"/private/var/lib/apt",
@"/private/var/lib/cydia",
@"/private/var/tmp/cydia.log",
@"/Applications/WinterBoard.app",
@"/var/lib/cydia",
@"/private/etc/dpkg/origins/debian",
@"/bin.sh",
@"/private/etc/apt",
@"/etc/ssh/sshd_config",
@"/private/etc/ssh/sshd_config",
@"/Applications/SBSetttings.app",
@"/private/var/mobileLibrary/SBSettingsThemes/",
@"/private/var/stash",
@"/usr/libexec/sftp-server",
@"/usr/libexec/cydia/",
@"/usr/sbin/frida-server",
@"/usr/bin/cycript",
@"/usr/local/bin/cycript",
@"/usr/lib/libcycript.dylib",
@"/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
@"/System/Library/LaunchDaemons/com.ikey.bbot.plist",
@"/Applications/FakeCarrier.app",
@"/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
@"/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
@"/usr/libexec/ssh-keysign",
@"/usr/libexec/sftp-server",
@"/Applications/blackra1n.app",
@"/Applications/IntelliScreen.app",
@"/Applications/Snoop-itConfig.app"
@"/var/lib/dpkg/info", nil];
//Check installed app
for(NSString* check in checks)
{
if(canOpen(check))
{
return YES;
}
}
defineHandler({
onEnter(log, args, state) {
var fileName = ObjC.Object(args[2]);
if (fileName.containsString_("apt") ||
fileName.containsString_("MobileSubstrate") ||
fileName.containsString_("Cydia") ||
fileName.containsString_("bash") ||
fileName.containsString_("ssh") ||
fileName.containsString_("/bin/sh") ||
fileName.containsString_("Applications") ||
fileName.containsString_("/bin/su") ||
fileName.containsString_("dpkg")) {
console.log('fileExistsAtPath called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
args[2] = ObjC.classes.NSString.stringWithString_("/xxxxxx");
log('[-NSFileManager fileExistsAtPath: ${fileName}]');
}
},
onLeave(log, retval, state) {
}
});
// frida-trace -U -f com.gemd.iting -m "-[NSFileManager fileExistsAtPath:]"
there are a lot of detection functions, hook them. This first wildcard matches either -
for an instance method or +
for a class method. the second *
means match all classes.
so, the full query *[* Jailb*]
breaks down as:
*
(first one): Match all instance (-
) and class (+
) methods.[
: Literal open bracket.*
: Match any class.]
: Literal close bracket.Jailb*
: Match any method name that starts with “Jailb”.
var resolver = new ApiResolver('objc');
resolver.enumerateMatches('*[* Jailb*]', {
onMatch: function (match) {
let funcName = match.name;
let funcAddr = match.address;
Interceptor.attach(ptr(funcAddr),{
onEnter: function (args) {},
onLeave: function (retval) {
if (retval.toInt32() === 1) {
retval.replace(0);
}
console.log(funcName, retval);
}
});
},
onComplete: function () {}
});
resolver.enumerateMatches('*[* JailB*]', {
onMatch: function (match) {
let funcName = match.name;
let funcAddr = match.address;
Interceptor.attach(ptr(funcAddr), {
onEnter: function (args) {},
onLeave: function (retval) {
console.log(funcName, retval);
}
});
},
onComplete: function () {}
});
resolver.enumerateMatches('*[* jailB*]', {
onMatch: function (match) {
let funcName = match.name;
let funcAddr = match.address;
Interceptor.attach(ptr(funcAddr), {
onEnter: function (args) {},
onLeave: function (retval) {
console.log(funcName, retval);
}
});
},
onComplete: function () {}
});
// frida -U -f com.gemd.iting -l hook_muti_functions.js
connect iphone by ssh
ssh is similar to adb, it connects window with ios
if type yes, next time even if it’s the same ip address but a difference SHA256, it will raise middle attack (?)
default password alpine
other user
ssh mobile@192.168.1.5(iphone ip address)
change password
server ip changed it shows man-in-middle attack
delete rsa key in PC
vim know_hosts
move the cursor to the fine row, typedd
to delete this row
pushEsc
and type :wq
in the latest ios 15.8.1 on iphone 6s
if you cant directly connect root account, it will show shit like “authority failed”. here’s the alternative approach
connect with user
ssh mobile@192.168.1.7
input mobile password, the default password is
alpine
, but i changed it into1234
after inputting the correct password, it will show
press any button, type
su root
or justsu
(I guess both are fine)input root password, mine is
alpine
basic knowledge
iOS Common Directories
- /bin: Stores user-level binary files, such as
cat
,chmod
,chown
. - /dev: Stores device files.
- /etc: Stores system scripts and configuration files, such as
passwd
,hosts
. This directory actually points to /private/etc. - /sbin: Stores system-level binary files, such as
mount
,dmesg
. - /tmp: Stores temporary files. This directory actually points to /private/var/tmp.
- /usr/lib: Stores various dylib dynamic libraries.
- /usr/include: Standard C header files.
- /usr/bin: Stores user-installed binary files. Commands for
ssh
,dpkg
, and Cydia are typically located here. - /var: Contains logs, user data, temporary files, App Store Apps, and the
/var/checkra1n.dmg
. - /var/root
- /var/mobile
iOS Directory Descriptions
- /Applications: All system apps and apps installed from Cydia.
- /Developer: Xcode development-related files and tools.
- /Library: Stores data that provides system support.
- /Library/MobileSubstrate/DynamicLibraries: Stores Cydia Substrate plugins.
- /System: Stores a large number of system components and frameworks.
- /System/Library/Frameworks: The location of frameworks like Foundation.framework.
- /System/Library/PrivateFrameworks
- /System/Library/CoreServices: Contains core services like the SpringBoard.app.
- /User: Actually points to /var/mobile, storing user data (photos, text messages, recordings).
- /User/Media
- /var/containers/Bundle/Application/xxxx/DoDoNew.app/: App Store app directory.
- /var/mobile/Containers/Data/Application/xxxx: App data directory (sandbox directory).
The command grep -ril DoDoNew ./*
is a command-line utility used to search for a string recursively within files.
decrypt an ipa
- crackerXI https://onejailbreak.com/blog/crackerxi/repository (recommend)
- DumpDecrypter
scp root@192.168.1.4:/var/mobile/Documents/DumpDecrypter/xxx.ipa ./ # move a file from iphone to windows
- frida-ios-dump
https://www.bilibili.com/video/BV1xWQaYMEhs/
https://github.com/AloneMonkey/frida-ios-dump#
dump.py -l # see the app list
CCCrypt
In the realm of iOS reverse engineering, CCCrypt is a fundamental function that frequently becomes a focal point for analysis. It resides within Apple’s CommonCrypto library, a low-level framework that provides cryptographic operations. Understanding and inspecting CCCrypt is crucial for security researchers and developers alike, as it underpins the encryption and decryption of data in a vast number of iOS applications.
What is CCCrypt and the CommonCrypto Library?
The CommonCrypto library offers a C-level API for a variety of cryptographic tasks. At its core, the CCCrypt
function provides symmetric-key encryption and decryption. This means the same key is used for both encrypting and decrypting data.
The function itself has the following signature:
CCCryptorStatus CCCrypt(
CCOperation op, // kCCEncrypt or kCCDecrypt
CCAlgorithm alg, // Algorithm (e.g., kCCAlgorithmAES)
CCOptions options, // Options (e.g., kCCOptionPKCS7Padding)
const void *key, // The encryption key
size_t keyLength, // Length of the key
const void *iv, // Initialization Vector (optional)
const void *dataIn, // Input data to be processed
size_t dataInLength, // Length of the input data
void *dataOut, // Buffer for the output data
size_t dataOutAvailable, // Size of the output buffer
size_t *dataOutMoved // On return, the number of bytes written
);
Reverse engineers pay close attention to this function because it’s where sensitive information is often handled. By intercepting calls to CCCrypt
, one can gain insight into how an application protects its data, what data is being protected, and potentially uncover vulnerabilities in the implementation.
Why is CCCrypt a Prime Target in Reverse Engineering?
Applications use CCCrypt
for a wide range of purposes, from securing user credentials and encrypting local files to protecting communication with a server. For a reverse engineer, analyzing these calls can reveal:
- Hardcoded Keys: Developers sometimes embed encryption keys directly within the application’s code. By tracing the
key
parameter ofCCCrypt
, these keys can often be extracted. - Weak Algorithms or Modes: An application might use an outdated or insecure encryption algorithm or mode of operation. For example, using ECB mode is generally discouraged as it can reveal patterns in the encrypted data.
- Static Initialization Vectors (IVs): The use of a static or predictable IV can significantly weaken the encryption.
- Sensitive Data in Plaintext: By examining the
dataIn
anddataOut
buffers, a reverse engineer can see the data before encryption and after decryption, potentially exposing sensitive user information, API keys, or proprietary data.
Analyzing CCCrypt with Frida
Frida is an indispensable tool for iOS reverse engineering, allowing for the dynamic instrumentation of running applications. With Frida, you can hook into the CCCrypt
function and inspect its arguments in real-time.
Here is a sample Frida script to trace CCCrypt
calls:
Interceptor.attach(Module.findExportByName('libcommonCrypto.dylib', 'CCCrypt'), {
onEnter: function(args) {
console.log('\n[+] Called CCCrypt');
console.log(' - CCOperation: ' + (args[0].toInt32() == 0 ? 'kCCEncrypt' : 'kCCDecrypt'));
// Further analysis of algorithm, options, key, IV, and data can be added here.
this.key = args[3];
this.keyLength = args[4].toInt32();
this.iv = args[5];
this.dataIn = args[6];
this.dataInLength = args[7].toInt32();
this.dataOut = args[8];
this.dataOutMoved = args[10];
},
onLeave: function(retval) {
console.log(' - Status: ' + retval.toInt32());
if (retval.toInt32() == 0) { // kCCSuccess
const dataOutMoved = this.dataOutMoved.readPointer().toInt32();
if (dataOutMoved > 0) {
console.log(' - Output Data (Hex): ' + this.dataOut.readByteArray(dataOutMoved));
}
}
console.log('[+] Finished CCCrypt');
}
});
from a github repo:
var encrypt_func = Module.findExportByName("libcommonCrypto.dylib", "CCCrypt");
Interceptor.attach(encrypt_func, {
onEnter: function (args) {
console.log("[+] CCCrypt function called");
console.log("[+] CCOperation: " + args[0].toInt32());
console.log("[+] CCAlgorithm: " + args[1].toInt32());
console.log("[+] CCOptions: " + args[2].toInt32());
console.log("[+] key: \n" + hexdump(ptr(args[3]), { length: args[4].toInt32() }));
console.log("[+] keyLength: \n" + args[4].toInt32());
console.log("[+] iv: \n" + hexdump(ptr(args[5]), { length: 16 }));
console.log("[+] dataIn: \n" + hexdump(ptr(args[6]), { length: args[7].toInt32() }));
console.log("[+] dataInLength: " + args[7].toInt32());
this.dataOutPtr = args[8];
this.dataOutLengthPtr = args[10];
},
onLeave: function (retval) {
console.log("[+] dataOut: \n" + hexdump(ptr(this.dataOutPtr), { length: ptr(this.dataOutLengthPtr).readUInt() }));
}
});
UI related knowledge
Checking the function of UI controls You can locate key code by using UI controls. It can distinguish whether an app is native or H5. The reverse engineering methods for apps developed in different forms are not the same. Most of the encryption for H5 apps is in JS, but a very small number of apps are in Objective-C (OC), or a mixture.
Introduction to Reveal Disadvantages:
- Not free
- Can only be used on Mac
- Configuration is relatively troublesome Advantages:
- Displays the UI more intuitively
**Frida to print UI ** https://github.com/teapot-4l8/FridaDev
use frida to list all bundle id
import frida
device = frida.get_usb_device()
session = device.attach("SpringBoard")
script = session.create_script("""
if (ObjC.available) {
var workspace = ObjC.classes.LSApplicationWorkspace.defaultWorkspace();
var apps = workspace.allInstalledApplications();
for (var i = 0; i < apps.count(); i++) {
var app = apps.objectAtIndex_(i);
try {
var name = app.localizedName();
var bundleId = app.applicationIdentifier();
console.log(name.toString() + " : " + bundleId.toString());
} catch (e) {}
}
}
""")
script.load()
use frida-ps -Uai
to check out name
and use the name
of app to print UI python fridaDev.py -u [Name]
if you see webview
, that app is made of a web. in www/
file, it have index.html
ps aux |grep [Name]
scp -r root@192.168.1.4:[xx/xx/x/xxx] [t]
Hook: Substitute VS ElleKit
The difference between Substitute and ElleKit in iOS Jailbreaking
If you’re using Dopamine, which is a rootless jailbreak, the default injection framework on your device is likely ElleKit, not Substitute.
- Dopamine is a modern, rootless jailbreak tool that supports devices with A12 chips and newer. It’s compatible with iOS versions ranging from 15.0 to 16.6.1 (though the specific support list may change).
- ElleKit is the code injection and hooking framework specifically designed for rootless jailbreaks. Its core function is similar to Substitute’s—modifying an app’s behavior at runtime—but it’s built to work within the rootless jailbreak environment.
The main difference between a rootless jailbreak and a traditional rootful one is that a rootless jailbreak installs all its files in the /var
directory instead of directly modifying the root filesystem (/
). This design makes the jailbreak more secure and easier to remove.
Because of this architectural difference, traditional hooking frameworks like the rootful version of Substitute can’t work directly in a rootless environment. That’s why rootless jailbreak tools like Dopamine use ElleKit as their default injection framework.
So, when you’re doing reverse engineering on a device with a Dopamine rootless jailbreak, you should be focusing on tools and tweaks that are compatible with ElleKit, not Substitute. Most modern tweak developers ensure compatibility with both frameworks, but some very old tweaks might only support Substitute.
develop extensions (tweaks)
system: Ubuntu 20.04
Theos: https://theos.dev/docs/
add nic.pl
to path
Clean up the previous incorrect lines:
First, you need to remove the incorrect lines you added to your .bashrc file. You can open the file with a simple editor like nano.
Bash
nano ~/.bashrc
In the file, find and delete the two lines you previously added.
Add the correct environment variables:
At the end of the file, add these two correctly configured lines:
Bash
export THEOS=/aaa/theos export PATH="$THEOS/bin:$PATH"
Note that on the second line, we use the
export
keyword to ensure thePATH
variable is available to sub-processes. We also use double quotes" "
to ensure the$THEOS
variable will be correctly expanded when the file is sourced, not when theecho
command is run.Save and exit:
In the nano editor, press Ctrl + O to save the file, then press Enter to confirm the filename. Next, press Ctrl + X to exit the editor.
Apply the changes immediately:
You don’t need to close and reopen your terminal. Run the following command to load the new .bashrc configuration:
Bash
source ~/.bashrc
Verify the setup:
Now you can try running the nic.pl command to check if it’s working. If everything is correct, it should display the usage information.
Bash
nic.pl
You can also use the
echo
command to verify that theTHEOS
andPATH
environment variables are set correctly:Bash
echo $THEOS echo $PATH
If the output shows
/aaa/theos
and/aaa/theos/bin
in the respective paths, your setup is successful.
other interesting shit
Share VPN
they should be LAN
ur vpn android device
v2yan: change socks5 and http port as the same number, allow coonections from the LAN
ur vpn not found window device
ios
this is clash. also change http and socks port and allow LAN
useful address
http://zhaoboy9692.github.io/repo
https://ids.ailiao.eu shared account :+1: :+1: :+1: :+1: