工具环境
ida7.0
iphone 6
ios 10.2

0x00:基本情况

1. 该app可以修改模拟手机地理位置(gps、基站、WIFI),拥有全局定位、指定应用定位、模拟扫街等功能,只能在已越狱的IOS系统上使用,安装须要用到Cydia,安装后主要分为插件与主程序两个部分,主程序负责与用户交互,插件主要实现了修改地理位置的功能。在Cydia插件安装目录可以找到它释放的xxtweak.dylib文件,拷贝出来后面做详细分析。

2. 程序运行后如果不是vip用户是不能使用修改定位的功能,如下:

0x01:保护机制分析

1. 将手机设置好代理,启动app登录,用抓包工具获取数据包做分析,发送到服务器的数据与服务器返回的数据都是加密的,如下图:

2. 通过动态调试主app来寻找突破口,主app通过sysctl来做反调试,先编写一个tweak来过掉反调试。这个代码网上很多,如下:

static int (*orig_sysctl)(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize);
static int my_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize){
int ret = orig_sysctl(name,namelen,info,infosize,newinfo,newinfosize);
if(namelen == && name[] == && name[] == && name[] == ){
struct kinfo_proc *info_ptr = (struct kinfo_proc *)info;
if(info_ptr && (info_ptr->kp_proc.p_flag & P_TRACED) != ){
NSLog(@"[AntiAntiDebug] - sysctl query trace status.");
info_ptr->kp_proc.p_flag ^= P_TRACED;
if((info_ptr->kp_proc.p_flag & P_TRACED) == ){
NSLog(@"[AntiAntiDebug] trace status reomve success!");
}
}
}
return ret;
}

3. 将app放入ida中反编,用登录抓包获取到的信息中关键字来查找字符串定位到组合参数的地方,组合后格式如下:

{
"data":"{
"clientid":"4092f7a187943eff48d1c4b827b5f53c",
"username":"xxxxx",//用户名
"password":"xxxxxx"//密码
}",
"header":{
"uptime":"",
"sysapi":"10.2",
"model":"iPhone 6",
"systype":"",
"vercode":"15.13",
"uuid":"DA148217C2491937"
}
}

然后将组合后的代码用AES加密发送到服务器代码如下:

void __cdecl -[TXYUserInfoRequset loginUserwith:andPassword:andClientid:](TXYUserInfoRequset *self, SEL a2, id a3, id a4, id a5)
{
id v5; // x21
id v6; // x20
TXYUserInfoRequset *v7; // x22
__int64 username; // x19
__int64 v9; // x1
__int64 passwrod; // x20
__int64 v11; // x1
__int64 v12; // x21
void *url; // x0
void *v14; // x0
void *v15; // x0
void *v16; // x24
void *v17; // x0
__int64 clientId; // x23
void *v19; // x0
const __CFString *v20; // x2
struct objc_object *v21; // x0
struct objc_object *v22; // ST28_8
id v23; // x0
__int64 v24; // ST20_8
id v25; // x0
void *v26; // x0
void *v27; // x28
void *v28; // x0
__int64 v29; // x25
void *v30; // x0
struct objc_object *v31; // ST18_8
id v32; // x0
struct objc_object *info_json; // x0
struct objc_object *v34; // x28
id ret; // x0
__int64 v36; // x21
void *v37; // x0
void *v38; // x26
double v39; // d0
void *v40; // x0
__int64 v41; // x25
void *v42; // x0
struct objc_object *bodydata; // x24
__int64 v44; // x1
NSURLSessionTask *v45; // x0
__int64 v46; // x0
struct objc_object *httpurl; // [xsp+38h] [xbp-138h]
void *v48; // [xsp+40h] [xbp-130h]
int v49; // [xsp+48h] [xbp-128h]
int v50; // [xsp+4Ch] [xbp-124h]
__int64 (__fastcall *v51)(__int64, __int64); // [xsp+50h] [xbp-120h]
void *v52; // [xsp+58h] [xbp-118h]
__int64 v53; // [xsp+60h] [xbp-110h]
const __CFString *body; // [xsp+68h] [xbp-108h]
const __CFString *v55; // [xsp+70h] [xbp-100h]
const __CFString *v56; // [xsp+78h] [xbp-F8h]
const __CFString *v57; // [xsp+80h] [xbp-F0h]
__int64 encdata; // [xsp+88h] [xbp-E8h]
const __CFString *v59; // [xsp+90h] [xbp-E0h]
const __CFString *v60; // [xsp+98h] [xbp-D8h]
__int64 v61; // [xsp+A0h] [xbp-D0h]
const __CFString *v62; // [xsp+A8h] [xbp-C8h]
const __CFString *v63; // [xsp+B0h] [xbp-C0h]
__int64 v64; // [xsp+B8h] [xbp-B8h]
__int64 v65; // [xsp+C0h] [xbp-B0h]
const __CFString *v66; // [xsp+C8h] [xbp-A8h]
const __CFString *v67; // [xsp+D0h] [xbp-A0h]
const __CFString *v68; // [xsp+D8h] [xbp-98h]
__int64 username_1; // [xsp+E0h] [xbp-90h]
__int64 passwrod_1; // [xsp+E8h] [xbp-88h]
__int64 clientId_1; // [xsp+F0h] [xbp-80h]
const __CFString *v72; // [xsp+F8h] [xbp-78h]
const __CFString *v73; // [xsp+100h] [xbp-70h]
__int64 v74; // [xsp+108h] [xbp-68h]
__int64 v75; // [xsp+110h] [xbp-60h]
__int64 v76; // [xsp+118h] [xbp-58h] v5 = a5;
v6 = a4;
v7 = self;
v76 = -7228227847426539268LL;
username = objc_retain(a3, a2);
passwrod = objc_retain(v6, v9);
v12 = objc_retain(v5, v11);
if ( !username )
{
v20 = CFSTR("缺少用户名");
LABEL_7:
objc_msgSend(v7, (const char *)&MEMORY[0x19AEA7047], v20);
clientId = v12;
goto LABEL_10;
}
if ( !passwrod )
{
v20 = CFSTR("缺少密码");
goto LABEL_7;
}
url = objc_msgSend(
&MEMORY[0x1B559E398],
(const char *)&MEMORY[0x1966A229A],
CFSTR("%@%@"),
CFSTR("http://ipay.txyapp.com:7658/api/entrance"),
CFSTR("/111"));
httpurl = (struct objc_object *)objc_retainAutoreleasedReturnValue(url);
v14 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
v15 = (void *)objc_retainAutoreleasedReturnValue(v14);
v16 = v15;
v17 = objc_msgSend(v15, (const char *)&MEMORY[0x1966A8093], CFSTR("clientId"));
clientId = objc_retainAutoreleasedReturnValue(v17);
objc_release(v12);
objc_release(v16);
if ( clientId )
{
username_1 = username;
v66 = CFSTR("username");
v67 = CFSTR("password");
passwrod_1 = passwrod;
v68 = CFSTR("clientid");
clientId_1 = clientId;
v19 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &username_1, &v66, 3LL);
}
else
{
v72 = CFSTR("username");
v73 = CFSTR("password");
v74 = username;
v75 = passwrod;
v19 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &v74, &v72, 2LL);
}
v21 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v19);
v22 = v21;
v23 = ((id (__cdecl *)(TXYUserInfoRequset *, SEL, id))objc_msgSend)(v7, "convertToJSONData:", v21);
v24 = objc_retainAutoreleasedReturnValue(v23);
v62 = CFSTR("data");
v63 = CFSTR("header");
v64 = v24;
v25 = ((id (__cdecl *)(DeviceAbout_meta *, SEL))objc_msgSend)(
(DeviceAbout_meta *)&OBJC_CLASS___DeviceAbout,
"sharedDevice");
v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
v27 = v26;
v28 = objc_msgSend(v26, "getPublicPhone");
v29 = objc_retainAutoreleasedReturnValue(v28);
v65 = v29;
v30 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &v64, &v62, 2LL);
v31 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v30);
objc_release(v29);
objc_release(v27);
v32 = ((id (__cdecl *)(TXYUserInfoRequset *, SEL, id))objc_msgSend)(v7, "convertToJSONData:", v31);
info_json = (struct objc_object *)objc_retainAutoreleasedReturnValue(v32);
v34 = info_json;
ret = ((id (__cdecl *)(AES128_meta *, SEL, id, id))objc_msgSend)(// 加密参数
(AES128_meta *)&OBJC_CLASS___AES128,
"AES128Encrypt:withKey:",
info_json,
(id)CFSTR("Hz2Ywe8UBe@YfZ0*"));
v36 = objc_retainAutoreleasedReturnValue(ret);
encdata = v36;
body = CFSTR("body");
v55 = CFSTR("type");
v59 = CFSTR("");
v56 = CFSTR("flag");
v60 = CFSTR("");
v57 = CFSTR("t1");
v37 = objc_msgSend(&MEMORY[0x1B5592FC0], (const char *)&MEMORY[0x1966B0E63]);
v38 = (void *)objc_retainAutoreleasedReturnValue(v37);
objc_msgSend(v38, (const char *)&MEMORY[0x19678A07E]);
v40 = objc_msgSend(&MEMORY[0x1B559E398], (const char *)&MEMORY[0x1966A229A], CFSTR("%lld"), (signed __int64)v39);
v41 = objc_retainAutoreleasedReturnValue(v40);
v61 = v41;
v42 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &encdata, &body, 4LL);
bodydata = (struct objc_object *)objc_retainAutoreleasedReturnValue(v42);
objc_release(v41);
objc_release(v38);
v48 = &MEMORY[0x1B558B298];
v49 = -;
v50 = ;
v51 = __60__TXYUserInfoRequset_loginUserwith_andPassword_andClientid___block_invoke_2;// 解密返回数并存放配置文件中
v52 = &__block_descriptor_tmp259;
v53 = objc_retain(v7, v44);
v45 = ((NSURLSessionTask *(__cdecl *)(TXYNetManager_meta *, SEL, unsigned __int64, id, id, id, id, id))objc_msgSend)(// 发送网络
(TXYNetManager_meta *)&OBJC_CLASS___TXYNetManager,
"txy_requestWithType:urlString:parameters:progress:successBlock:failureBlock:",
1uLL,
httpurl,
bodydata,
(id)&__block_literal_global240,
(id)&v48,
(id)&__block_literal_global262);
v46 = objc_retainAutoreleasedReturnValue(v45);
objc_release(v46);
objc_release(v53);
objc_release(bodydata);
objc_release(v36);
objc_release(v34);
objc_release(v31);
objc_release(v24);
objc_release(v22);
objc_release(httpurl);
LABEL_10:
objc_release(clientId);
objc_release(passwrod);
objc_release(username);
}

4. 解密与解析服务器返回的数据,解密后数据格式如下:

{
"status":,
"token":"de9dc56d7d7cc085f4bb1897075e4801",
"username":"xxxx",//用户名
"vip":, //是否为vip用户
"expiretime": //会员过期时间
}

解密代码如下:

/ 登录后存放authValue到文件
__int64 __fastcall __60__TXYUserInfoRequset_loginUserwith_andPassword_andClientid___block_invoke_2(__int64 a1, __int64 a2)
{
__int64 v2; // x28
__int64 v3; // x19
void *v4; // x0
void *v5; // x21
__int64 v6; // x1
void *v7; // x19
void *v8; // x0
__int64 v9; // x22
void *v10; // x0
__int64 v11; // x23
void *v12; // x0
__int64 v13; // ST10_8
void *v14; // x0
void *v15; // x23
void *v16; // x24
void *v17; // x0
struct objc_object *data; // x0
struct objc_object *v19; // x24
id v20; // x0
void *v21; // x0
void *v22; // x28
void *v23; // x0
__int64 v24; // x0
void *v25; // x0
void *v26; // x0
void *v27; // x26
void *v28; // x0
__int64 v29; // ST08_8
void *v30; // x0
void *v31; // x23
void *v32; // x22
void *v33; // x0
__int64 v34; // x22
__int64 v35; // x23
void *v36; // x20
void *v37; // x0
__int64 v38; // x21
__int64 v39; // x0
void *v40; // x0
__int64 v41; // x22
void *v42; // x0
__int64 v43; // ST00_8
void *v44; // x0
void *v45; // x23
void *v46; // x0
__int64 v47; // x28
void *v48; // x0
__int64 v49; // x22
void *v50; // x0
__int64 v51; // ST00_8
void *v52; // x0
void *v53; // x23
void *v54; // x0
__int64 v55; // x22
void *v56; // x0
__int64 v57; // x22
__int64 v58; // x24
void *v59; // x0
void *v60; // x23
void *v61; // x22
void *v62; // x0
void *v63; // x0
void *v64; // x23
void *v65; // x0
__int64 v66; // x24
void *v67; // x0
__int64 v68; // x0
__int64 v69; // x22
__int64 v70; // x0
void *v71; // x0
void *v72; // x22
int vip; // w24
id v74; // x0
void *v75; // x0
void *v76; // x23
void *v77; // x0
void *v78; // x28
void *v79; // x0
__int64 v80; // x24
void *v81; // x0
__int64 v82; // x23
void *v83; // x0
void *v84; // x23
id v85; // x0
void *v86; // x0
__int64 v87; // x24
void *v88; // x0
__int64 v89; // x23
void *v90; // x0
void *v91; // x22
void *v92; // x0
__int64 v93; // x21
void *v94; // x0
__int64 v95; // x20
__int64 v97; // [xsp+0h] [xbp-90h]
void *v98; // [xsp+20h] [xbp-70h]
struct objc_object *v99; // [xsp+28h] [xbp-68h]
__int64 v100; // [xsp+30h] [xbp-60h]
__int64 v101; // [xsp+38h] [xbp-58h]
__int64 v102; // [xsp+38h] [xbp-58h] v2 = a1;
v3 = objc_retain(a2, a2);
v4 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
v5 = (void *)objc_retainAutoreleasedReturnValue(v4);
objc_msgSend(v5, (const char *)&MEMORY[0x1966A8EE2], CFSTR("no"), CFSTR("geostates"));
objc_release(v5);
v7 = (void *)objc_retain(v3, v6);
NSLog(CFSTR("response====%@"));
v8 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("error"), v7);
v9 = objc_retainAutoreleasedReturnValue(v8);
v10 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("info"));
v11 = objc_retainAutoreleasedReturnValue(v10);
v12 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("status"));
v13 = objc_retainAutoreleasedReturnValue(v12);
NSLog(CFSTR("error = %@ info = %@ status = %@"));
objc_release(v13);
objc_release(v11);
objc_release(v9);
v14 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("status"), v9, v11, v13);
v15 = (void *)objc_retainAutoreleasedReturnValue(v14);
v16 = objc_msgSend(v15, (const char *)&MEMORY[0x1966A5F6B]);
objc_release(v15);
if ( !v16 ) // 判断网络是否返回成功
{
v101 = v2;
v17 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("data"));// 获取返回值中的data数据
data = (struct objc_object *)objc_retainAutoreleasedReturnValue(v17);
v19 = data;
v20 = ((id (__cdecl *)(AES128_meta *, SEL, id, id))objc_msgSend)(// 解密data数据
(AES128_meta *)&OBJC_CLASS___AES128,
"AES128Decrypt:withKey:",
data,
(id)CFSTR("Hz2Ywe8UBe@YfZ0*"));
v21 = (void *)objc_retainAutoreleasedReturnValue(v20);
v22 = v21;
v23 = objc_msgSend(v21, (const char *)&MEMORY[0x196754444], 4LL);
v24 = objc_retainAutoreleasedReturnValue(v23);
v100 = v24;
v25 = objc_msgSend(&MEMORY[0x1B55A0FF8], (const char *)&MEMORY[0x197C763B3], v24, 1LL, 0LL);
v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
v27 = v26;
v28 = objc_msgSend(v26, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
v29 = objc_retainAutoreleasedReturnValue(v28);
NSLog(CFSTR("----%@ -------%@"));
objc_release(v29);
v30 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("status"), v27, v29);
v31 = (void *)objc_retainAutoreleasedReturnValue(v30);
v32 = objc_msgSend(v31, (const char *)&MEMORY[0x1966A5F6B]);
objc_release(v31);
if ( v32 )
{
v33 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
v34 = objc_retainAutoreleasedReturnValue(v33);
objc_release(v34);
v35 = v100;
if ( !v34 )
{
LABEL_21:
objc_release(v27);
objc_release(v35);
objc_release(v22);
objc_release(v19);
goto LABEL_22;
}
v36 = *(void **)(v101 + );
v37 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
v38 = objc_retainAutoreleasedReturnValue(v37);
objc_msgSend(v36, (const char *)&MEMORY[0x19AEA7047], v38);
v39 = v38;
}
else
{
v98 = v22;
v40 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("token"));
v41 = objc_retainAutoreleasedReturnValue(v40);
objc_release(v41);
if ( v41 )
{
v42 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("token"));
v43 = objc_retainAutoreleasedReturnValue(v42);
NSLog(CFSTR("%@"));
objc_release(v43);
v44 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA], v43);
v45 = (void *)objc_retainAutoreleasedReturnValue(v44);
v46 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("token"));
v47 = objc_retainAutoreleasedReturnValue(v46);
objc_msgSend(v45, (const char *)&MEMORY[0x1966A8EE2], v47, CFSTR("token"));
objc_release(v47);
objc_release(v45);
}
v99 = v19;
v48 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("username"));
v49 = objc_retainAutoreleasedReturnValue(v48);
objc_release(v49);
if ( v49 )
{
v50 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("username"));
v51 = objc_retainAutoreleasedReturnValue(v50);
NSLog(CFSTR("%@"));
objc_release(v51);
v52 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA], v51);
v53 = (void *)objc_retainAutoreleasedReturnValue(v52);
v54 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("username"));
v55 = objc_retainAutoreleasedReturnValue(v54);
objc_msgSend(v53, (const char *)&MEMORY[0x1966A8EE2], v55, CFSTR("userName"));
objc_release(v55);
objc_release(v53);
}
v56 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("expiretime"));
v57 = objc_retainAutoreleasedReturnValue(v56);
objc_release(v57);
v58 = v101;
if ( v57 )
{
v59 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("expiretime"));
v60 = (void *)objc_retainAutoreleasedReturnValue(v59);
v61 = objc_msgSend(v60, (const char *)&MEMORY[0x1966ABDF3]);
objc_release(v60);
v62 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
v63 = (void *)objc_retainAutoreleasedReturnValue(v62);
v64 = v63;
if ( (_DWORD)v61 )
{
v65 = objc_msgSend(*(void **)(v101 + ), "timeFormatted:", v61);
v66 = objc_retainAutoreleasedReturnValue(v65);
objc_msgSend(v64, (const char *)&MEMORY[0x1966A8EE2], v66, CFSTR("expiretime"));
objc_release(v66);
objc_release(v64);
v58 = v101;
v67 = objc_msgSend(*(void **)(v101 + ), "timeFormatted:", v61);
v68 = objc_retainAutoreleasedReturnValue(v67);
v69 = v68;
v97 = v68;
NSLog(CFSTR("expiretime = %@ "));
v70 = v69;
}
else
{
objc_msgSend(v63, (const char *)&MEMORY[0x1966A8EE2], CFSTR(""), CFSTR("expiretime"));
v70 = (__int64)v64;
}
objc_release(v70);
}
v102 = v58;
v71 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("vip"), v97);
v72 = (void *)objc_retainAutoreleasedReturnValue(v71);
vip = (unsigned __int64)objc_msgSend(v72, (const char *)&MEMORY[0x1966ABDF3]);
objc_release(v72);
v74 = ((id (__cdecl *)(TXYTools_meta *, SEL))objc_msgSend)((TXYTools_meta *)&OBJC_CLASS___TXYTools, "sharedTools");
v75 = (void *)objc_retainAutoreleasedReturnValue(v74);
v76 = v75;
v77 = objc_msgSend(v75, "loadSetDictForPath:", CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"));
v78 = (void *)objc_retainAutoreleasedReturnValue(v77);
objc_release(v76);
if ( vip ) // 如果vip不为0
{
v79 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 1LL);
v80 = objc_retainAutoreleasedReturnValue(v79);
objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v80, CFSTR("authValue"));
objc_release(v80);
v81 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 1LL);
v82 = objc_retainAutoreleasedReturnValue(v81);
objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v82, CFSTR("Toggle"));
objc_release(v82);
v83 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
v84 = (void *)objc_retainAutoreleasedReturnValue(v83);
objc_msgSend(v84, (const char *)&MEMORY[0x1966A8EE2], CFSTR(""), CFSTR("isVIP"));
}
else // 如果vip为0
{
v86 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 0LL);
v87 = objc_retainAutoreleasedReturnValue(v86);
objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v87, CFSTR("authValue"));
objc_release(v87);
v88 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 0LL);
v89 = objc_retainAutoreleasedReturnValue(v88);
objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v89, CFSTR("Toggle"));
objc_release(v89);
v90 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
v84 = (void *)objc_retainAutoreleasedReturnValue(v90);
objc_msgSend(v84, (const char *)&MEMORY[0x1966A8EE2], CFSTR(""), CFSTR("isVIP"));
}
objc_release(v84);
v85 = ((id (__cdecl *)(TXYTools_meta *, SEL))objc_msgSend)((TXYTools_meta *)&OBJC_CLASS___TXYTools, "sharedTools");
v91 = (void *)objc_retainAutoreleasedReturnValue(v85);
objc_msgSend(v91, "writeDict:toPath:", v78, CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"));// 写入配置文件
objc_release(v91);
objc_release(v78);
v35 = v100;
v22 = v98;
v19 = v99;
v92 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
v93 = objc_retainAutoreleasedReturnValue(v92);
objc_release(v93);
if ( v93 )
objc_msgSend(*(void **)(v102 + ), (const char *)&MEMORY[0x19AEA7047], CFSTR("登录成功"));
v94 = objc_msgSend(*(void **)(v102 + ), "requestResult");
v95 = objc_retainAutoreleasedReturnValue(v94);
(*(void (**)(void))(v95 + ))();
v39 = v95;
}
objc_release(v39);
goto LABEL_21;
}
LABEL_22:
objc_release(v7);
return objc_release(v7);
}

1. 整个登录过程就分析完成了,主要用到了AES加密算法。

0x02:破解思路

1. 通过上面登录过程的分析,根据上面数据格式可以直接改vip与expiretime的值就能成功破解成会员用户,如下图 :

2. 将服务器返回的值存入.plist文件后,程序会调用-[TXYTools isCanOpen]方法读取文件判断是否为vip,代码如下:

  bool __cdecl -[TXYTools isCanOpen](TXYTools *self, SEL a2)
{
void *v2; // x0
void *v3; // x0
void *v4; // x20
void *v5; // x0
void *v6; // x23
void *isVIP; // x19
id v8; // x0
void *v9; // x0
void *v10; // x23
void *v11; // x0
void *v12; // x20
void *v13; // x0
void *v14; // x23
void *authValue; // x21 v2 = objc_msgSend(&OBJC_CLASS___NSUserDefaults, (const char *)&unk_188A615FA);
v3 = (void *)objc_retainAutoreleasedReturnValue(v2);
v4 = v3;
v5 = objc_msgSend(v3, (const char *)&unk_188A60093, CFSTR("isVIP"));
v6 = (void *)objc_retainAutoreleasedReturnValue(v5);
isVIP = objc_msgSend(v6, (const char *)&unk_188A5DF6B);
objc_release(v6);
objc_release(v4);
v8 = ((id (__cdecl *)(TXYTools_meta *, SEL))objc_msgSend)((TXYTools_meta *)&OBJC_CLASS___TXYTools, "sharedTools");
v9 = (void *)objc_retainAutoreleasedReturnValue(v8);
v10 = v9;
v11 = objc_msgSend(v9, "loadSetDictForPath:", CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"));
v12 = (void *)objc_retainAutoreleasedReturnValue(v11);
objc_release(v10);
v13 = objc_msgSend(v12, (const char *)&unk_188A60093, CFSTR("authValue"));
v14 = (void *)objc_retainAutoreleasedReturnValue(v13);
authValue = objc_msgSend(v14, (const char *)&unk_188A5DF6B);
objc_release(v14);
NSLog(CFSTR("user = %ld"));
NSLog(CFSTR("isVIP = %ld"));
objc_release(v12);
return (signed __int64)isVIP > && (signed __int64)authValue > ;
}

3. 第一是可以通过修改服务器返回值做破解,第二是通过hook方法isCanOpen来做破解。代码如下 :

%hook TXYTools
- (BOOL)isCanOpen
{
return YES;
}
%end

破解成功后可以正常使用功能,如下图所示 :

0x03:实现原理

1. 主app获取到要修改的经纬度与地名后DES加密存放在.plist配置文件中,将选择的地图上的经纬度与地址名加密后写入.plist配置文件,代码如下:

//将选择的app的Build地图上的经纬度与地址名加密后写入.plist配置文件
__int64 __fastcall -[TXYConfig setLocationWithBundleId:andType:andGPS:withAddress:withIsOn:](void *a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, double a7, double a8)
{
__int64 v8; // x26
__int64 v9; // x19
double v10; // d8
double v11; // d9
__int64 v12; // x25
void *v13; // x20
__int64 v14; // x1
const __CFString *v15; // x19
void *v16; // x0
void *v17; // x0
void *v18; // x21
void *v19; // x0
__int64 v20; // x1
void *v21; // x22
void *v22; // x0
void *v23; // x0
__int64 v24; // x0
__int64 v25; // x28
void *v26; // x0
__int64 v27; // x0
__int64 v28; // x24
void *v29; // x0
__int64 v30; // x0
__int64 v31; // x20
void *v32; // x0
void *v33; // x26
void *v34; // x0
__int64 v35; // x20
void *v36; // x0
__int64 v37; // x20
__int64 v39; // [xsp+10h] [xbp-C0h]
__int64 v40; // [xsp+18h] [xbp-B8h]
void *v41; // [xsp+20h] [xbp-B0h]
const __CFString *v42; // [xsp+28h] [xbp-A8h]
const __CFString *v43; // [xsp+30h] [xbp-A0h]
const __CFString *v44; // [xsp+38h] [xbp-98h]
const __CFString *v45; // [xsp+40h] [xbp-90h]
__int64 v46; // [xsp+48h] [xbp-88h]
__int64 v47; // [xsp+50h] [xbp-80h]
const __CFString *v48; // [xsp+58h] [xbp-78h]
__int64 v49; // [xsp+60h] [xbp-70h]
__int64 v50; // [xsp+68h] [xbp-68h] v8 = a6;
v9 = a5;
v10 = a8;
v11 = a7;
v12 = a4;
v13 = a1;
v40 = a3;
v41 = a1;
v50 = -7228227847426539268LL;
v39 = objc_retain(a3, a2);
v15 = (const __CFString *)objc_retain(v9, v14);
v16 = objc_msgSend(v13, "loadSetDict");
v17 = (void *)objc_retainAutoreleasedReturnValue(v16);
v18 = v17;
v19 = objc_msgSend(v17, (const char *)&unk_1966A8093, CFSTR("AppLocation"));
v21 = (void *)objc_retainAutoreleasedReturnValue(v19);
if ( !v21 )
{
v22 = objc_msgSend(&OBJC_CLASS___NSMutableDictionary, (const char *)&unk_1966A833B);
v21 = (void *)objc_retainAutoreleasedReturnValue(v22);
}
if ( !(_DWORD)v12 )
{
objc_retain(CFSTR("跟随系统真实位置"), v20);
objc_release(v15);
v15 = CFSTR("跟随系统真实位置");
}
v42 = CFSTR("Latitude");
v23 = objc_msgSend(&OBJC_CLASS___NSNumber, (const char *)&unk_1966A25C1, v11);
v24 = objc_retainAutoreleasedReturnValue(v23);
v25 = v24;
v46 = v24;
v43 = CFSTR("Longitude");
v26 = objc_msgSend(&OBJC_CLASS___NSNumber, (const char *)&unk_1966A25C1, v10);
v27 = objc_retainAutoreleasedReturnValue(v26);
v28 = v27;
v47 = v27;
v44 = CFSTR("address");
v48 = v15;
v45 = CFSTR("isOn");
v29 = objc_msgSend(&OBJC_CLASS___NSNumber, &aNumberwithbool, v8);
v30 = objc_retainAutoreleasedReturnValue(v29);
v31 = v30;
v49 = v30;
v32 = objc_msgSend(&OBJC_CLASS___NSDictionary, &aDictionarywith, &v46, &v42, 4LL);
v33 = objc_msgSend(v32, "mutableCopy");
objc_release(v31);
objc_release(v28);
objc_release(v25);
v34 = objc_msgSend(&OBJC_CLASS___NSNumber, &aNumberwithunsi, v12);
v35 = objc_retainAutoreleasedReturnValue(v34);
objc_msgSend(v33, &aSetobjectForke, v35, CFSTR("FakeType"));
objc_release(v35);
objc_msgSend(v21, &aSetobjectForke, v33, v40);
objc_release(v39);
v36 = objc_msgSend(&OBJC_CLASS___NSNumber, &aNumberwithbool, 1LL);
v37 = objc_retainAutoreleasedReturnValue(v36);
objc_msgSend(v18, &aSetobjectForke, v37, CFSTR("Toggle"));
objc_release(v37);
objc_msgSend(v18, &aSetobjectForke, v21, CFSTR("AppLocation"));
NSLog(CFSTR("%@"));
objc_msgSend(v41, "writeSetConfigWithDict:", v18, v18);// 加密并写入配置文件
objc_release(v33);
objc_release(v21);
objc_release(v18);
return objc_release(v15);
} //加密并写入配置文件
bool __cdecl -[TXYConfig writeSetConfigWithDict:](TXYConfig *self, SEL a2, id a3)
{
void *v3; // x0
__int64 v4; // x19
void *v5; // x0
void *v6; // x0
void *v7; // x20
struct objc_object *v8; // x0
void *v9; // x21
char v10; // w22
__int64 v12; // [xsp+8h] [xbp-28h] v3 = objc_msgSend(&OBJC_CLASS___NSJSONSerialization, &aDatawithjsonob, a3, 1LL, 0LL);
v4 = objc_retainAutoreleasedReturnValue(v3);
v5 = objc_msgSend(&OBJC_CLASS___NSString, &aAlloc_0);
v6 = objc_msgSend(v5, &aInitwithdataEn, v4, 4LL);
v7 = v6;
v8 = +[DES encryptString:](&OBJC_CLASS___DES, "encryptString:", v6);// des加密
v9 = (void *)objc_retainAutoreleasedReturnValue(v8);
v12 = 0LL;
v10 = (unsigned __int64)objc_msgSend(
v9,
&aWritetofileAto,
CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"),
0LL,
4LL,
&v12);
objc_release(v9);
objc_release(v7);
objc_release(v4);
return v10;
}
id __cdecl +[DES encryptString:](DES_meta *self, SEL a2, id a3)
{
return (id)objc_msgSend(self, "TripleDES:encryptOrDecrypt:key:", a3, 0LL, CFSTR("3b38e11ffd65698aedeb5ffc"));
}

2. Tweak插件主要是hook了几个函数,当目标程序调用获取地理位置信息函数时就解密主app加密存放好的值做为获取值,代码如下:

Hook获取位置函数

char *__fastcall _logosLocalCtor_3415ee8c(int a1, char **a2, char **a3)
{
void *v3; // ST30_8
__int64 v4; // x0
__int64 v5; // x8
const char *v7; // [xsp+0h] [xbp-4C0h]
const char *v8; // [xsp+8h] [xbp-4B8h]
signed __int64 v9; // [xsp+10h] [xbp-4B0h]
const char *v10; // [xsp+18h] [xbp-4A8h]
void *v11; // [xsp+20h] [xbp-4A0h]
char v12; // [xsp+58h] [xbp-468h]
__int64 v13; // [xsp+70h] [xbp-450h]
int v14; // [xsp+7Ch] [xbp-444h]
__int64 CLLocationManager; // [xsp+80h] [xbp-440h]
__int64 v16; // [xsp+88h] [xbp-438h]
char **v17; // [xsp+90h] [xbp-430h]
char **v18; // [xsp+98h] [xbp-428h]
int v19; // [xsp+A4h] [xbp-41Ch]
char v20; // [xsp+A8h] [xbp-418h]
char v21; // [xsp+A9h] [xbp-417h]
char v22; // [xsp+AAh] [xbp-416h]
char v23; // [xsp+ABh] [xbp-415h]
char v24; // [xsp+ACh] [xbp-414h]
char v25; // [xsp+ADh] [xbp-413h]
char v26; // [xsp+AEh] [xbp-412h]
char v27; // [xsp+AFh] [xbp-411h] v19 = a1;
v18 = a2;
v17 = a3;
v16 = objc_getClass("AMapLocationManager");
if ( v16 )
{
MSHookMessageEx(
v16,
"detectRiskOfFakeLocation",
_logos_method$_ungrouped$AMapLocationManager$detectRiskOfFakeLocation,// 检测虚拟定位
&_logos_orig$_ungrouped$AMapLocationManager$detectRiskOfFakeLocation);
}
else
{
v11 = objc_msgSend(&OBJC_CLASS___NSString, "stringWithFormat:", CFSTR("logos: nil class %s"), "AMapLocationManager");
v10 = "ERROR";
v9 = 276LL;
v8 = "Tweak.xm";
v7 = "txytweak";
CFLog(3LL, CFSTR("\x1B[1;31m[%s] \x1B[m\x1B[0;31m%s:%d\x1B[m \x1B[0;30;41m%s:\x1B[m %@"));
}
CLLocationManager = objc_getClass("CLLocationManager");
if ( CLLocationManager )
{
MSHookMessageEx(
CLLocationManager,
"location",
_logos_method$_ungrouped$CLLocationManager$location,
&_logos_orig$_ungrouped$CLLocationManager$location);
}
else
{
v11 = objc_msgSend(
&OBJC_CLASS___NSString,
"stringWithFormat:",
CFSTR("logos: nil class %s"),
"CLLocationManager",
v8,
v9,
v10,
v11);
v10 = "ERROR";
v9 = 276LL;
v8 = "Tweak.xm";
v7 = "txytweak";
CFLog(3LL, CFSTR("\x1B[1;31m[%s] \x1B[m\x1B[0;31m%s:%d\x1B[m \x1B[0;30;41m%s:\x1B[m %@"));
}
if ( CLLocationManager )
{
MSHookMessageEx(
CLLocationManager,
"startUpdatingLocation",
_logos_method$_ungrouped$CLLocationManager$startUpdatingLocation,
&_logos_orig$_ungrouped$CLLocationManager$startUpdatingLocation);
}
else
{
v11 = objc_msgSend(
&OBJC_CLASS___NSString,
"stringWithFormat:",
CFSTR("logos: nil class %s"),
"CLLocationManager",
v8,
v9,
v10,
v11);
v10 = "ERROR";
v9 = 276LL;
v8 = "Tweak.xm";
v7 = "txytweak";
CFLog(3LL, CFSTR("\x1B[1;31m[%s] \x1B[m\x1B[0;31m%s:%d\x1B[m \x1B[0;30;41m%s:\x1B[m %@"));
}
v20 = ;
v21 = ;
v22 = ;
v23 = ;
v24 = ;
v25 = ;
v26 = ;
v14 = ;
v27 = ;
class_addMethod();
v13 = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationCenterAddObserver();
objc_msgSend(&OBJC_CLASS___NSBundle, "mainBundle", v7, v8, v9, v10, v11);
v3 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v3, "bundleIdentifier");
v4 = objc_retainAutoreleasedReturnValue();
v5 = curBundle;
curBundle = v4;
objc_release(v5);
objc_release(v3);
NSLog(CFSTR("txy hook success1111111"));
return &v12;
}

读取 .plist配置文中的数据并解密。

void __cdecl -[TXYLocation replacedLocationManager:didUpdateToLocation:fromLocation:](TXYLocation *self, SEL a2, id a3, id a4, id a5)
{
void *v5; // ST2F8_8
__int64 v6; // x0
void *v7; // ST1F0_8
void *v8; // x0
void *v9; // ST1E0_8
void *v10; // ST1D0_8
char v11; // ST1CC_1
void *v12; // ST2A8_8
void *v13; // ST1B8_8
double v14; // d0
double v15; // ST2C0_8
void *v16; // ST1A8_8
double v17; // d0
double v18; // ST2C8_8
__int64 v19; // ST2A0_8
void *v20; // ST1A0_8
double v21; // d0
double v22; // ST198_8
double v23; // d0
double v24; // ST190_8
double v25; // d0
double v26; // ST188_8
double v27; // ST180_8
double v28; // d0
double v29; // d0
double v30; // d1
void *v31; // ST150_8
void *v32; // ST148_8
int v33; // ST144_4
void *v34; // ST258_8
void *v35; // ST138_8
double v36; // d0
void *v37; // ST130_8
double v38; // d0
void *v39; // ST128_8
int v40; // ST124_4
void *v41; // ST238_8
void *v42; // ST118_8
double v43; // d0
void *v44; // ST110_8
double v45; // d0
void *v46; // STF8_8
double v47; // d0
double v48; // STE8_8
double v49; // d0
double v50; // STD8_8
double v51; // d0
double v52; // STC8_8
double v53; // d0
double v54; // STB8_8
double v55; // d0
double v56; // STA8_8
__int64 v57; // x0
__int64 v58; // ST98_8
void *v59; // x0
__int64 v60; // x9
void *v61; // ST88_8
double v62; // d0
double v63; // ST80_8
double v64; // d0
double v65; // ST78_8
double v66; // d0
double v67; // ST70_8
double v68; // d0
double v69; // ST68_8
double v70; // d0
double v71; // ST60_8
__int64 v72; // ST58_8
void *v73; // ST50_8
double v74; // d0
double v75; // ST48_8
double v76; // d0
double v77; // ST40_8
double v78; // d0
double v79; // ST38_8
double v80; // d0
double v81; // ST30_8
double v82; // d0
double v83; // ST28_8
__int64 v84; // ST20_8
double v85; // d0
double v86; // d1
double v87; // d2
double v88; // d3
char v89; // [xsp+15Ch] [xbp-1E4h]
char v90; // [xsp+1DCh] [xbp-164h]
char v91; // [xsp+1ECh] [xbp-154h]
void *v92; // [xsp+228h] [xbp-118h]
char v93; // [xsp+267h] [xbp-D9h]
void *v94; // [xsp+268h] [xbp-D8h]
unsigned int v95; // [xsp+274h] [xbp-CCh]
double v96; // [xsp+290h] [xbp-B0h]
void *v97; // [xsp+298h] [xbp-A8h]
void *v98; // [xsp+2B0h] [xbp-90h]
void *v99; // [xsp+2B8h] [xbp-88h]
double v100; // [xsp+2C0h] [xbp-80h]
double v101; // [xsp+2C8h] [xbp-78h]
void *v102; // [xsp+2D0h] [xbp-70h]
void *jsondata; // [xsp+2E8h] [xbp-58h]
struct objc_object *v104; // [xsp+300h] [xbp-40h]
TXYLocation *v105; // [xsp+328h] [xbp-18h] v105 = self;
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
NSLog(CFSTR("第一个方法相应"));
objc_msgSend(
&OBJC_CLASS___NSString,
"stringWithContentsOfFile:encoding:error:",
CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"),
4LL,
0LL);
v104 = (struct objc_object *)objc_retainAutoreleasedReturnValue();
if ( v104 )
{
((void (__cdecl *)(DES_meta *, SEL, id))objc_msgSend)((DES_meta *)&OBJC_CLASS___DES, "decryptString:", v104);// 解密
v5 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v5, "dataUsingEncoding:", 4LL);
v6 = objc_retainAutoreleasedReturnValue();
objc_msgSend(&OBJC_CLASS___NSJSONSerialization, "JSONObjectWithData:options:error:", v6, 1LL, 0LL);
jsondata = (void *)objc_retainAutoreleasedReturnValue();
if ( !jsondata )
{
objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
jsondata = (void *)objc_retainAutoreleasedReturnValue();
objc_release(0LL);
}
objc_msgSend(jsondata, "valueForKey:", CFSTR("Toggle"));
v7 = (void *)objc_retainAutoreleasedReturnValue();
v91 = (unsigned __int64)objc_msgSend(v7, "boolValue");
objc_release(v7);
if ( objc_retain(CFSTR("/var/mobile/Library/Preferences/com.txy.FakeStatus.plist")) )
{
v8 = objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "alloc");
v102 = objc_msgSend(
v8,
"initWithContentsOfFile:",
CFSTR("/var/mobile/Library/Preferences/com.txy.FakeStatus.plist"));
objc_release(0LL);
if ( !v102 )
{
objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
v102 = (void *)objc_retainAutoreleasedReturnValue();
objc_release(0LL);
}
}
else
{
objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
v102 = (void *)objc_retainAutoreleasedReturnValue();
objc_release(0LL);
}
objc_msgSend(v102, "objectForKey:", CFSTR("fakeStatus"));
v9 = (void *)objc_retainAutoreleasedReturnValue();
v90 = (unsigned __int64)objc_msgSend(v9, "isEqualToString:", CFSTR("no"));
objc_release(v9);
if ( !(v91 & ) )
{
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
LABEL_36:
v95 = ;
LABEL_37:
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
if ( v95 )
goto LABEL_41;
goto LABEL_40;
}
objc_msgSend(jsondata, "objectForKey:", CFSTR("AppLocation"));
v99 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(jsondata, "objectForKey:", CFSTR("AppScan"));
v98 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v98, "allKeys");
v10 = (void *)objc_retainAutoreleasedReturnValue();
v11 = (unsigned __int64)objc_msgSend(v10, "containsObject:", curBundle);
objc_release(v10);
if ( v11 & )
{
objc_msgSend(v98, "objectForKey:", curBundle);
v12 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v12, "objectForKey:", CFSTR("Latitude"));
v13 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v13, "doubleValue");
v15 = v14;
objc_release(v13);
objc_msgSend(v12, "objectForKey:", CFSTR("Longitude"));
v16 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v16, "doubleValue");
v18 = v17;
objc_release(v16);
objc_msgSend(&OBJC_CLASS___NSDate, "date");
v19 = objc_retainAutoreleasedReturnValue();
v20 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
objc_msgSend(0LL, "altitude");
v22 = v21;
objc_msgSend(0LL, "horizontalAccuracy");
v24 = v23;
objc_msgSend(0LL, "verticalAccuracy");
v26 = v25;
v27 = *(double *)&lastCourse;
objc_msgSend(0LL, "speed");
v97 = objc_msgSend(
v20,
"initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
v19,
v15,
v18,
v22,
v24,
v26,
v27,
v28);
objc_msgSend((void *)lastFakeFromLocation, "coordinate");
v96 = headingToLocation(v15, v18, v29, v30);
objc_storeStrong();
if ( v96 != 0.0 )
lastCourse = *(_QWORD *)&v96;
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, v97, v97);
v95 = ;
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
goto LABEL_33;
}
v93 = ;
v89 = ;
if ( v99 )
{
objc_msgSend(v99, "allKeys");
v94 = (void *)objc_retainAutoreleasedReturnValue();
v93 = ;
v89 = (unsigned __int64)objc_msgSend(v94, "containsObject:", curBundle);
}
if ( v93 & )
objc_release(v94);
if ( v89 & )
{
objc_msgSend(v99, "objectForKeyedSubscript:", curBundle);
v31 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v31, "objectForKeyedSubscript:", CFSTR("isOn"));
v32 = (void *)objc_retainAutoreleasedReturnValue();
v33 = (unsigned __int64)objc_msgSend(v32, "intValue");
objc_release(v32);
objc_release(v31);
if ( v33 != )
{
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
v95 = ;
goto LABEL_33;
}
objc_msgSend(v99, "objectForKey:", curBundle);
v34 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v34, "objectForKey:", CFSTR("Latitude"));
v35 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v35, "doubleValue");
v100 = v36;
objc_release(v35);
objc_msgSend(v34, "objectForKey:", CFSTR("Longitude"));
v37 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v37, "doubleValue");
v101 = v38;
objc_release(v37);
objc_msgSend(v34, "objectForKey:", CFSTR("FakeType"));
v39 = (void *)objc_retainAutoreleasedReturnValue();
v40 = (unsigned __int64)objc_msgSend(v39, "intValue");
objc_release(v39);
if ( v40 )
{
v95 = ;
}
else
{
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
v95 = ;
}
objc_storeStrong();
if ( v95 )
{
LABEL_33:
objc_storeStrong();
objc_storeStrong();
if ( v95 )
goto LABEL_37;
goto LABEL_36;
}
}
else
{
if ( (v90 & ) != )
{
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
v95 = ;
goto LABEL_33;
}
objc_msgSend(jsondata, "objectForKey:", CFSTR("FakeLocation"));
v41 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v41, "objectForKey:", CFSTR("FakeLatitude"));
v42 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v42, "doubleValue");
v100 = v43;
objc_release(v42);
objc_msgSend(v41, "objectForKey:", CFSTR("FakeLongitude"));
v44 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v44, "doubleValue");
v101 = v45;
objc_release(v44);
objc_storeStrong();
}
if ( lastFakeFromLocation )
{
v73 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
objc_msgSend(0LL, "altitude");
v75 = v74;
objc_msgSend(0LL, "horizontalAccuracy");
v77 = v76;
objc_msgSend(0LL, "verticalAccuracy");
v79 = v78;
objc_msgSend(0LL, "course");
v81 = v80;
objc_msgSend(0LL, "speed");
v83 = v82;
objc_msgSend(0LL, "timestamp");
v84 = objc_retainAutoreleasedReturnValue();
v92 = objc_msgSend(
v73,
"initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
v84,
v100,
v101,
v75,
v77,
v79,
v81,
v83);
objc_release(0LL);
objc_release(v84);
}
else
{
v46 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
objc_msgSend(0LL, "altitude");
v48 = v47;
objc_msgSend(0LL, "horizontalAccuracy");
v50 = v49;
objc_msgSend(0LL, "verticalAccuracy");
v52 = v51;
objc_msgSend(0LL, "course");
v54 = v53;
objc_msgSend(0LL, "speed");
v56 = v55;
objc_msgSend(0LL, "timestamp");
v57 = objc_retainAutoreleasedReturnValue();
v58 = v57;
v59 = objc_msgSend(
v46,
"initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
v57,
v100,
v101,
v48,
v50,
v52,
v54,
v56);
v60 = lastFakeFromLocation;
lastFakeFromLocation = (__int64)v59;
objc_release(v60);
objc_release(v58);
v61 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
objc_msgSend(0LL, "altitude");
v63 = v62;
objc_msgSend(0LL, "horizontalAccuracy");
v65 = v64;
objc_msgSend(0LL, "verticalAccuracy");
v67 = v66;
objc_msgSend(0LL, "course");
v69 = v68;
objc_msgSend(0LL, "speed");
v71 = v70;
objc_msgSend(0LL, "timestamp");
v72 = objc_retainAutoreleasedReturnValue();
v92 = objc_msgSend(
v61,
"initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
v72,
v100,
v101,
v63,
v65,
v67,
v69,
v71);
objc_release(0LL);
objc_release(v72);
}
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, v92, v92);
objc_storeStrong();
objc_storeStrong();
v95 = ;
goto LABEL_33;
}
_objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
LABEL_40:
v95 = ;
LABEL_41:
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
objc_storeStrong();
if ( v95 > )
headingToLocation(v85, v86, v87, v88);
}

0x04:总结

1. 虽然与服务器交互的数据是加密的,但软件保护逻辑比较简单,实现修改地理位置的功能主要是通过hook获取位置的函数。

欢迎关注公众号

某虚拟定位APP从破解到原理分析的更多相关文章

  1. 支付宝app支付java后台流程、原理分析(含nei wang chuan tou)

    java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写     一.流程步骤         1.执行流程           当手机端app(就是你公司开发的app)在支付 ...

  2. IOS 微信、QQ、叮叮等APP虚拟定位 实在太好用了

    前不久爱思助手更新了最新版本:V7.96,同时更新了好几个功能,包括给ios设备修改虚拟定位功能,想要给手机修改,我们需要电脑下载爱思助手最新版本V7.96,数据线连接电脑修改. 借助爱思助手的虚拟定 ...

  3. iOS App的加固保护原理

    本文由  网易云发布. 本文从攻防原理层面解析了iOS APP的安全策略.iOS以高安全性著称,但它并非金刚不坏之身.对于信息安全而言,止大风于青萍之末是上上策,杭研深入各个细节的研发工作,正是网易产 ...

  4. android黑科技系列——分析某直播App的协议加密原理以及调用加密方法进行协议参数构造

    一.前言 随着直播技术火爆之后,各家都出了直播app,早期直播app的各种请求协议的参数信息都没有做任何加密措施,但是慢慢的有人开始利用这个后门开始弄刷粉关注工具,可以让一个新生的小花旦分分钟变成网红 ...

  5. android开发检测用户是否使用了虚拟定位

    在应用开发中,如果有签到打卡之类的功能,你是否会遇到检测用户是否使用了虚拟定位软件来进行打卡?如果有,那么请仔细阅读这篇文章.该文章会带你认识什么是虚拟定位.什么是应用分身,以及如何通过代码来检测用户 ...

  6. iPhone Anywehre虚拟定位提示“后台服务未启动,请重新安装应用后使用”的解决方法

    问题描述: iPhone越狱了,之后在Cydia中安装Anywhere虚拟定位,但是打开app提示:后台服务未启动,请重新安装应用后使用. 程序无法正常使用... 解决方法: 打开Cydia-已安装, ...

  7. IOS免越狱虚拟定位修改工具共享 Jocation

    Jocation IOS虚拟定位修改器 具体使用方法可以按照 location cleaned软件相同的操作. 主要是因为本人有一部 IphoneX 和Iphone Xs Max 网上的locatio ...

  8. 安卓虚拟定位软件Fake Location重大更新

    前段时间网上找安卓虚拟定位的软件,找了很久,大部分都是多开修改APP,或者是不可用的,最后在KUAN找到一个作者Lerist做的虚拟定位软件 Fake Location ,配合作者本人的一键解锁sys ...

  9. (转)Android 系统 root 破解原理分析

    现在Android系统的root破解基本上成为大家的必备技能!网上也有很多中一键破解的软件,使root破解越来越容易.但是你思考过root破解的 原理吗?root破解的本质是什么呢?难道是利用了Lin ...

随机推荐

  1. svn学习笔记(一)

    一.svn介绍 1.1 项目管理中的版本控制问题 通常软件开发由多人协作开发,如果对代码文件.配置文件.文档等没有进行版本控制,将会出现很多问题: 备份多个版本,占用磁盘空间大 解决代码冲突困难 容易 ...

  2. 校园网络安全CTF 第一题 和 你真了解我吗?

    第一题: 需要先找到相应头(REsponse header中的tips) <?php$flag = "***";if (isset($_GET['repo']))//检测变量 ...

  3. ElementUI 时间控件

    <template> <div class="block"> <span class="demonstration">默认& ...

  4. SPOJ - DISUBSTR 求串中子串的个数

    \(height\)简单应用 #include<iostream> #include<cstdio> #include<cstring> #include<c ...

  5. 1141 PAT Ranking of Institutions (25 分)

    After each PAT, the PAT Center will announce the ranking of institutions based on their students' pe ...

  6. 1137 Final Grading (25 分)

    For a student taking the online course "Data Structures" on China University MOOC (http:// ...

  7. python3.6 子类的__init__调用父类的__init__

    python3.6 子类的__init__调用父类的__init__ 父类 class worker: def __init__(self): self.a=1 self.b=2 if __name_ ...

  8. BaaS_后端即服务 RESTful

    码云coding API https://open.coding.net/ Swagger 官网用VPN能流畅打开,但它自己的基于web的编辑器不行 用来设计RESTful API LeanCloud ...

  9. Single Vendor Project in OpenStack

    1.astara: ptl: name: Ryan Petrello irc: ryanpetrello email: ryan.petrello@dreamhost.com irc-channel: ...

  10. 两种请求方式URLHttpconnection 和Httpclient提交表单 网络篇(二)

    安卓有两种发送请求的方式:URLHttpconnection 和Httpclient 下面就来讲下这两种方式,这篇是最基础的使用 进阶请看第二篇  先占位 打扫卫生去了T T 快过年了 框架就放网络篇 ...