工具环境
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. 6、C++共用体

    6.共用体 共用体(union)是一种数据格式,他能够存储不同的数据类型,但只能同时存储其中的一种类型.也就是说,结构可以同时存储int.long和double,共用体只能存储ing.long.dou ...

  2. iframe里面的元素触发父窗口元素事件的jquery代码 转

    例如父窗口定义了一个事件. top: $(dom1).bind('topEvent', function(){}); 那么iframe里面的元素怎样触发父窗口dom1的事件呢?这样吗? $(dom1, ...

  3. ScrollView-电影列表

    ScrollView 的使用import React, { Component } from 'react';import { Platform, StyleSheet, Text, View, Sc ...

  4. scp命令限速远程拷贝

    示例: 限速40M拷贝 scp -rl 358400 expdp_all_3schema_20180427* 172.16.16.36:/data/dmpold/

  5. 瀑布模型,(增量开发)渐增式开发,原型化开发,统一过程模型(RUP)

    瀑布模型:设计在开发阶段 瀑布模型有以下优点 1)为项目提供了按阶段划分的检查点. 2)当前一阶段完成后,您只需要去关注后续阶段. 3)可在迭代模型中应用瀑布模型. 增量迭代应用于瀑布模型.迭代1解决 ...

  6. Javascript 连接两个数组

    JS合并两个数组的方法 我们在项目过程中,有时候会遇到需要将两个数组合并成为一个的情况.比如: var a = [1,2,3]; var b = [4,5,6]; 有两个数组a.b,需求是将两个数组合 ...

  7. css flex 使内容 水平居中 的方法...

    刚开始以为是  justify-content : center 设置为 居中... 的确,,当 元素满了时 的确能 居中.但是 当只有一个元素时,这一个元素也会居中... 想了半天没找到方法..突然 ...

  8. C++_异常5-异常规范和栈解退

    异常规范 异常规范的理念看似有前途,但实际的使用效果并不好. 忽视异常规范之前,您至少应该知道它是什么样的,如下所示: double harm(double a) throw(bad_thing);  ...

  9. POJ_2478 Farey Sequence 【欧拉函数+简单递推】

    一.题目 The Farey Sequence Fn for any integer n with n >= 2 is the set of irreducible rational numbe ...

  10. dotnet体系结构

    一.C#与.NET的关系 1.粗略地説,.net是一种在Windows平台上的编程架构————一种API. 2.C#编译器专门用于.net,这表示用C#编写的所有代码总是使用.NET Framewor ...