前言:
电子取证类的比赛给我一种做试卷的感觉大部分的基础题然后会有少部分的难题,对于简单的题目主要靠的就是一些简单的推理,平时比赛会有很多专业的取证软件可以使用所以很多时候并不一定需要知道某些东西的原理也能通过专业软件提供的信息解题。对于电子取证类的比赛需要的基础首先是linux系统基础知识,然后就是web网站搭建知识。在这个基础上再去get新技能。下面的例子是21年第三届长安杯的比赛题目,之所以使用这个案例是因为这个案例涉及的基础知识还蛮多的,题目也感觉没有那么死板比较适合初学者了解电子取证,并对电子取证框架有一个比较深的了解。当然这些只是我的个人观点。
前期准备:
案件背景:
2021年4月25日,上午8点左右,警方接到被害人金某报案,声称自己被敲诈数万元;经询问,昨日金某被嫌疑人诱导裸聊, 下载了某“裸聊”软件,导致自己的通讯录和裸聊视频被嫌疑人获取,对其进行敲诈,最终金某不堪重负,选择了报警;警 方从金某提供的本人手机中,定向采集到了该“裸聊”软件的安装包--zhibo.apk(检材一),请各位回答下列问题:(题目 中需要通过分析出来的答案对检材二三四五解压,解压密码为IP的情况,需要在密码后增加-CAB2021,例: 192.168.100.100-CAB2021)
上面是这次案件的背景,在了解案件背景的时候还需要特别留意一下案件发生的时间,这点还是比较重要的,在做取证题时需要对整个案件的脉络和人物关系理清楚。接着看一下这次案件的检材
检材解密:
上面就是这个案件的所有检材,这里补充一个点就是由于案件检材的体量较大,检材一般都是提前几天下发下来供参赛选手提前下载,为了避免参赛选手在下载到检材后对检材提前进行密码爆破,往往检材会通过veracrypt这个开源工具对检材进行加密,上图的检材一&二这个没有后缀名的检材文件就是经过veracrypt进行加密。在比赛开始后官方会下发加密的密码,参赛选手就可以通过veracrypt对检材进行解密,具体操作步骤如下:
检材一&二密码为:2021第三届CAB-changancup.com。打开veracrypt软件如下图点击选择文件
然后选择检材一&二,之后随便选择一个盘符进行挂载,点击加载按钮:
在弹出密码框中输入上面的密码,点击确认即可。
等veracrypt解密完后,就可以看到磁盘已经挂载成功了:
案件分析:
在解密完检材后看看题目要求:
从题目内容可以看出检材一是一个apk文件,检材二和三是服务器检材,检材四里面有PC端的检材和手机检材。还有需要注意的是,后面几个检材的解压密码,前面某题的答案。
检材一分析:
data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
1.请计算检材一Apk的SHA256值。
前几题就是所谓的送分题,获得APK的SHA256值还是很简单的,随便找个哈希值计算工具都可以计算出来,我这里使用的是鸿联的雷电APK分析工具直接算出来的。后面几题也都可以通过雷电APK分析工具直接做出来。
2.该APK的应用包名为
这个包名的查找不使用专门的取证工具可以考虑使用apk反汇编工具对apk进行反汇编,这里我使用的是jadx将apk文件反汇编后在资源文件中点击AndroidManifest.xml,包名就在<manifest>
标签中的 package
属性:
3.该APK程序在封装服务商的应用唯一标识(APPID)为
**appId
**是用于唯一标识应用程序的标识符,其实就是上题plus.H5B8E45D3
中的H5B8E45D3
4.该APK具备下列哪些危险权限(多选题): ABCDE
A.读取短信.B.读取通讯录.C.读取精确位置.D.修改通讯录.E.修改短信
这一题有一个比较取巧的办法就是将这个APK文件直接安装到一个手机模拟器软件中一般app在安装时会询问权限
根据上面的权限信息可以发现上面出现的几个选项这里全都有。这个方法是个比较取巧的办法,正经解法是:
还是在AndroidManifest中有一些uses-permission
标签这里面就是apk需要的权限,可以查看下面t权限表一一对比。
访问登记属性 | android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 |
---|---|
获取错略位置 | android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米 |
获取精确位置 | android.permission.ACCESS_FINE_LOCATION,通过GPS芯片接收卫星的定位信息,定位精度达10米以内 |
访问定位额外命令 | android.permission.ACCESS_LOCATION_EXTRA_COMMANDS,允许程序访问额外的定位提供者指令 |
获取模拟定位信息 | android.permission.ACCESS_MOCK_LOCATION,获取模拟定位信息,一般用于帮助开发者调试应用 |
获取网络状态 | android.permission.ACCESS_NETWORK_STATE,获取网络信息状态,如当前的网络连接是否有效 |
访问Surface Flinger | android.permission.ACCESS_SURFACE_FLINGER,Android平台上底层的图形显示支持,一般用于游戏或照相机预览界面和底层模式的屏幕截图 |
获取WiFi状态 | android.permission.ACCESS_WIFI_STATE,获取当前WiFi接入的状态以及WLAN热点的信息 |
账户管理 | android.permission.ACCOUNT_MANAGER,获取账户验证信息,主要为GMail账户信息,只有系统级进程才能访问的权限 |
验证账户 | android.permission.AUTHENTICATE_ACCOUNTS,允许一个程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息 |
电量统计 | android.permission.BATTERY_STATS,获取电池电量统计信息 |
绑定小插件 | android.permission.BIND_APPWIDGET,允许一个程序告诉appWidget服务需要访问小插件的数据库,只有非常少的应用才用到此权限 |
绑定设备管理 | android.permission.BIND_DEVICE_ADMIN,请求系统管理员接收者receiver,只有系统才能使用 |
绑定输入法 | android.permission.BIND_INPUT_METHOD ,请求InputMethodService服务,只有系统才能使用 |
绑定RemoteView | android.permission.BIND_REMOTEVIEWS,必须通过RemoteViewsService服务来请求,只有系统才能用 |
绑定壁纸 | android.permission.BIND_WALLPAPER,必须通过WallpaperService服务来请求,只有系统才能用 |
使用蓝牙 | android.permission.BLUETOOTH,允许程序连接配对过的蓝牙设备 |
蓝牙管理 | android.permission.BLUETOOTH_ADMIN,允许程序进行发现和配对新的蓝牙设备 |
变成砖头 | android.permission.BRICK,能够禁用手机,非常危险,顾名思义就是让手机变成砖头 |
应用删除时广播 | android.permission.BROADCAST_PACKAGE_REMOVED,当一个应用在删除时触发一个广播 |
收到短信时广播 | android.permission.BROADCAST_SMS,当收到短信时触发一个广播 |
连续广播 | android.permission.BROADCAST_STICKY,允许一个程序收到广播后快速收到下一个广播 |
WAP PUSH广播 | android.permission.BROADCAST_WAP_PUSH,WAP PUSH服务收到后触发一个广播 |
拨打电话 | android.permission.CALL_PHONE,允许程序从非系统拨号器里输入电话号码 |
通话权限 | android.permission.CALL_PRIVILEGED,允许程序拨打电话,替换系统的拨号器界面 |
拍照权限 | android.permission.CAMERA,允许访问摄像头进行拍照 |
改变组件状态 | android.permission.CHANGE_COMPONENT_ENABLED_STATE,改变组件是否启用状态 |
改变配置 | android.permission.CHANGE_CONFIGURATION,允许当前应用改变配置,如定位 |
改变网络状态 | android.permission.CHANGE_NETWORK_STATE,改变网络状态如是否能联网 |
改变WiFi多播状态 | android.permission.CHANGE_WIFI_MULTICAST_STATE,改变WiFi多播状态 |
改变WiFi状态 | android.permission.CHANGE_WIFI_STATE,改变WiFi状态 |
清除应用缓存 | android.permission.CLEAR_APP_CACHE,清除应用缓存 |
清除用户数据 | android.permission.CLEAR_APP_USER_DATA,清除应用的用户数据 |
底层访问权限 | android.permission.CWJ_GROUP,允许CWJ账户组访问底层信息 |
手机优化大师扩展权限 | android.permission.CELL_PHONE_MASTER_EX,手机优化大师扩展权限 |
控制定位更新 | android.permission.CONTROL_LOCATION_UPDATES,允许获得移动网络定位信息改变 |
删除缓存文件 | android.permission.DELETE_CACHE_FILES,允许应用删除缓存文件 |
删除应用 | android.permission.DELETE_PACKAGES,允许程序删除应用 |
电源管理 | android.permission.DEVICE_POWER,允许访问底层电源管理 |
应用诊断 | android.permission.DIAGNOSTIC,允许程序到RW到诊断资源 |
禁用键盘锁 | android.permission.DISABLE_KEYGUARD,允许程序禁用键盘锁 |
转存系统信息 | android.permission.DUMP,允许程序获取系统dump信息从系统服务 |
状态栏控制 | android.permission.EXPAND_STATUS_BAR,允许程序扩展或收缩状态栏 |
工厂测试模式 | android.permission.FACTORY_TEST,允许程序运行工厂测试模式 |
使用闪光灯 | android.permission.FLASHLIGHT,允许访问闪光灯 |
强制后退 | android.permission.FORCE_BACK,允许程序强制使用back后退按键,无论Activity是否在顶层 |
访问账户Gmail列表 | android.permission.GET_ACCOUNTS,访问GMail账户列表 |
获取应用大小 | android.permission.GET_PACKAGE_SIZE,获取应用的文件大小 |
获取任务信息 | android.permission.GET_TASKS,允许程序获取当前或最近运行的应用 |
允许全局搜索 | android.permission.GLOBAL_SEARCH,允许程序使用全局搜索功能 |
硬件测试 | android.permission.HARDWARE_TEST,访问硬件辅助设备,用于硬件测试 |
注射事件 | android.permission.INJECT_EVENTS,允许访问本程序的底层事件,获取按键、轨迹球的事件流 |
安装定位提供 | android.permission.INSTALL_LOCATION_PROVIDER,安装定位提供 |
安装应用程序 | android.permission.INSTALL_PACKAGES,允许程序安装应用 |
内部系统窗口 | android.permission.INTERNAL_SYSTEM_WINDOW,允许程序打开内部窗口,不对第三方应用程序开放此权限 |
访问网络 | android.permission.INTERNET,访问网络连接,可能产生GPRS流量 |
结束后台进程 | android.permission.KILL_BACKGROUND_PROCESSES,允许程序调用killBackgroundProcesses(String).方法结束后台进程 |
管理账户 | android.permission.MANAGE_ACCOUNTS,允许程序管理AccountManager中的账户列表 |
管理程序引用 | android.permission.MANAGE_APP_TOKENS,管理创建、摧毁、Z轴顺序,仅用于系统 |
高级权限 | android.permission.MTWEAK_USER,允许mTweak用户访问高级系统权限 |
社区权限 | android.permission.MTWEAK_FORUM,允许使用mTweak社区权限 |
软格式化 | android.permission.MASTER_CLEAR,允许程序执行软格式化,删除系统配置信息 |
修改声音设置 | android.permission.MODIFY_AUDIO_SETTINGS,修改声音设置信息 |
修改电话状态 | android.permission.MODIFY_PHONE_STATE,修改电话状态,如飞行模式,但不包含替换系统拨号器界面 |
格式化文件系统 | android.permission.MOUNT_FORMAT_FILESYSTEMS,格式化可移动文件系统,比如格式化清空SD卡 |
挂载文件系统 | android.permission.MOUNT_UNMOUNT_FILESYSTEMS,挂载、反挂载外部文件系统 |
允许NFC通讯 | android.permission.NFC,允许程序执行NFC近距离通讯操作,用于移动支持 |
永久Activity | android.permission.PERSISTENT_ACTIVITY,创建一个永久的Activity,该功能标记为将来将被移除 |
处理拨出电话 | android.permission.PROCESS_OUTGOING_CALLS,允许程序监视,修改或放弃播出电话 |
读取日程提醒 | android.permission.READ_CALENDAR,允许程序读取用户的日程信息 |
读取联系人 | android.permission.READ_CONTACTS,允许应用访问联系人通讯录信息 |
屏幕截图 | android.permission.READ_FRAME_BUFFER,读取帧缓存用于屏幕截图 |
读取收藏夹和历史记录 | com.android.browser.permission.READ_HISTORY_BOOKMARKS,读取浏览器收藏夹和历史记录 |
读取输入状态 | android.permission.READ_INPUT_STATE,读取当前键的输入状态,仅用于系统 |
读取系统日志 | android.permission.READ_LOGS,读取系统底层日志 |
读取电话状态 | android.permission.READ_PHONE_STATE,访问电话状态 |
读取短信内容 | android.permission.READ_SMS,读取短信内容 |
读取同步设置 | android.permission.READ_SYNC_SETTINGS,读取同步设置,读取Google在线同步设置 |
读取同步状态 | android.permission.READ_SYNC_STATS,读取同步状态,获得Google在线同步状态 |
重启设备 | android.permission.REBOOT,允许程序重新启动设备 |
开机自动允许 | android.permission.RECEIVE_BOOT_COMPLETED,允许程序开机自动运行 |
接收彩信 | android.permission.RECEIVE_MMS,接收彩信 |
接收短信 | android.permission.RECEIVE_SMS,接收短信 |
接收Wap Push | android.permission.RECEIVE_WAP_PUSH,接收WAP PUSH信息 |
录音 | android.permission.RECORD_AUDIO,录制声音通过手机或耳机的麦克 |
排序系统任务 | android.permission.REORDER_TASKS,重新排序系统Z轴运行中的任务 |
结束系统任务 | android.permission.RESTART_PACKAGES,结束任务通过restartPackage(String)方法,该方式将在外来放弃 |
发送短信 | android.permission.SEND_SMS,发送短信 |
设置Activity观察其 | android.permission.SET_ACTIVITY_WATCHER,设置Activity观察器一般用于monkey测试 |
设置闹铃提醒 | com.android.alarm.permission.SET_ALARM,设置闹铃提醒 |
设置总是退出 | android.permission.SET_ALWAYS_FINISH,设置程序在后台是否总是退出 |
设置动画缩放 | android.permission.SET_ANIMATION_SCALE,设置全局动画缩放 |
设置调试程序 | android.permission.SET_DEBUG_APP,设置调试程序,一般用于开发 |
设置屏幕方向 | android.permission.SET_ORIENTATION,设置屏幕方向为横屏或标准方式显示,不用于普通应用 |
设置应用参数 | android.permission.SET_PREFERRED_APPLICATIONS,设置应用的参数,已不再工作具体查看addPackageToPreferred(String) 介绍 |
设置进程限制 | android.permission.SET_PROCESS_LIMIT,允许程序设置最大的进程数量的限制 |
设置系统时间 | android.permission.SET_TIME,设置系统时间 |
设置系统时区 | android.permission.SET_TIME_ZONE,设置系统时区 |
设置桌面壁纸 | android.permission.SET_WALLPAPER,设置桌面壁纸 |
设置壁纸建议 | android.permission.SET_WALLPAPER_HINTS,设置壁纸建议 |
发送永久进程信号 | android.permission.SIGNAL_PERSISTENT_PROCESSES,发送一个永久的进程信号 |
状态栏控制 | android.permission.STATUS_BAR,允许程序打开、关闭、禁用状态栏 |
访问订阅内容 | android.permission.SUBSCRIBED_FEEDS_READ,访问订阅信息的数据库 |
写入订阅内容 | android.permission.SUBSCRIBED_FEEDS_WRITE,写入或修改订阅内容的数据库 |
显示系统窗口 | android.permission.SYSTEM_ALERT_WINDOW,显示系统窗口 |
更新设备状态 | android.permission.UPDATE_DEVICE_STATS,更新设备状态 |
使用证书 | android.permission.USE_CREDENTIALS,允许程序请求验证从AccountManager |
使用SIP视频 | android.permission.USE_SIP,允许程序使用SIP视频服务 |
使用振动 | android.permission.VIBRATE,允许振动 |
唤醒锁定 | android.permission.WAKE_LOCK,允许程序在手机屏幕关闭后后台进程仍然运行 |
写入GPRS接入点设置 | android.permission.WRITE_APN_SETTINGS,写入网络GPRS接入点设置 |
写入日程提醒 | android.permission.WRITE_CALENDAR,写入日程,但不可读取 |
写入联系人 | android.permission.WRITE_CONTACTS,写入联系人,但不可读取 |
写入外部存储 | android.permission.WRITE_EXTERNAL_STORAGE,允许程序写入外部存储,如SD卡上写文件 |
写入Google地图数据 | android.permission.WRITE_GSERVICES,允许程序写入Google Map服务数据 |
写入收藏夹和历史记录 | com.android.browser.permission.WRITE_HISTORY_BOOKMARKS,写入浏览器历史记录或收藏夹,但不可读取 |
读写系统敏感设置 | android.permission.WRITE_SECURE_SETTINGS,允许程序读写系统安全敏感的设置项 |
读写系统设置 | android.permission.WRITE_SETTINGS,允许读写系统设置项 |
编写短信 | android.permission.WRITE_SMS,允许编写短信 |
写入在线同步设置 | android.permission.WRITE_SYNC_SETTINGS,写入Google在线同步设置 |
5.该APK发送回后台服务器的数据包含一下哪些内容(多选题):
A.手机通讯录.B.手机应用列表.C.手机号码.D.验证码.E.GPS定位信息.
这个题的解法可以从两个方向下手一个是逆向apk分析源代码,一个是抓包之后观察数据包内容,先看第一种解法,之前在分析AndroidManifest.xml文件时有看到包名处有dcloud等字样
DCloud平台经常用于开发基于WebView的应用,根据这个线索可以首先看一下这个apk是不是网站打包后的apk文件,回到jadx,找找这个反汇编项目的资源文件:
可以看到这里面躺着一个网站文件夹,先看一下index.html
中的代码
这些html代码就是apk的首页代码,在这个html代码的末尾还引用了一段js代码,不过是经过sojson加密的
这段代码出现在这就非常可疑了,sojson加密很好解决,直接将这段加密代码放到在线sojson解密网站进行解密
将解密后的代码复制出来进行分析(如果嫌麻烦直接丢给chatgpt)
经过chatgpt的一通分析发现代码中名为huoqu的函数获取了一些信息然后发送给了服务器:
整合上面的信息该apk获取了手机通讯录,手机号,邀请码,GPS定位。(address文件在chatgpt中没有给全,这个变量在同文件的一个函数中是赋了值的)
第二种解法:
将apk文件放到模拟器里,对fiddler进行配置,然后在手机上下载安全证书进行抓包
可以看抓到目标服务器的地址
6.该APK程序回传通讯录时,使用的http请求方式为()
这里还是前面分析的js代码,其中有一段代码:
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) {
//异常处理;
}
});
可以看到使用的是POST请求
7.该APK程序的回传地址域名为【标准格式:www.abc.com】 :
前面通过抓包已经看到了回传的地址域名为www.honglian7001.com
8.该APK程序代码中配置的变量apiserver的值为【标准格式:www.abc.com/abc】
同样还是看上面解密后的js代码直接搜索该变量即可:
9.分析该APK,发现该程序还具备获取短信回传到后台的功能,短信上传服务器接口地址为【标准格式:www.abc.com/abc】
继续审计js代码,可以发现短信上传服务器的接口地址是由变量 apiserver
和字符串 'apisms'
组合而成的:www.honglian7001.com/api/uploads/apisms
10.经分析,发现该APK在运行过程中会在手机中产生一个数据库文件,该文件的文件名为
这个题的思路是直接在jadx中全局搜索.db字样会出现几个结果
接着跟进这几个可能的选项分析代码(不会的直接问chatgpt就行),最后可以确定产生的数据库的文件名为test.db,这里看一下相关代码
代码解析:
120行负责初始化一个test.db的数据库,然后121行到122行就是生成这个数据库的密钥,具体生成过程为
bytesToHex(key)
: 将**key
**字节数组转换为十六进制字符串,即616263646566
。.substring(1, 3)
: 从上一步的结果中获取下标1和下标2这两个元素作为子字符串。即,16
getMD5(...)
: 对上一步的结果进行MD5哈希。
11.经分析,发现该APK在运行过程中会在手机中产生一个数据库文件,该数据库的初始密码为
根据前面的分析密钥就是16的MD5值,如果觉得不够保险也可以自己写个java脚本复现一下上述操作
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HelloWorld {
public static void main(String []args) {
byte[] key = {97, 98, 99, 100, 101, 102};
System.out.println(getMD5(bytesToHex(key).substring(1, 3)));
}
public static String getMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
return bytesToHex(digest);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
最后密钥为:
检材二分析:
题目有说第七题的答案是检材二的解压密码:
第七题的答案为www.honglian7001.com
。解压成功之后可以看到是一个E01镜像文件:
这时候可以分为两步走,第一步是使用专业的取证软件比如弘连的火眼证据分析软件,美亚的取证大师对镜像进行分析,第二步是将镜像仿真成虚拟机文件,然后运行起来进行分析。关于镜像的仿真同样可以试用弘连的火眼仿真进行虚拟机文件转换,但是没有仿真软件也不要紧,可以使用FTK对E01镜像进行挂载,具体操作可参考:
虚拟机跑起来后,还有一个问题需要注意,就是运行之后需要密码登录,这里可以搜索相关系统的修改密码办法
12.检材二的原始硬盘的SHA256值为:
前面说过解法,这里不过多赘述
13.查询涉案于案发时间段内登陆服务器的IP地址为【标准格式:111.111.111.111】
这个题的重点是得先知道案发时间是啥时候,已知的时间点是报案时间为4月25日,而根据金先生所述他是昨天下的裸聊软件
所以我们基本可以确定案发时间是4月24,输入last命令查看历史登录
14.请对检材二进行分析,并回答该服务器在集群中承担的主要作用是(负载均衡服务器)【格式:文件存储】
通过查看history查看命令(通过仿真软件或者仿真都可以看到)
通过对历史命令的分析可以发现,使用者在频繁的使用这个文件夹,所以cd过去看他的readme
通过读他的readme可以了解到const大概就是端口号配置文件所在的地方,而ADProxy.js是反向代理目标地址的配置文件
15.上一题中,提到的主要功能对应的服务监听的端口为:80
进入配置文件可以直切看到这些信息
16.上一题中,提到的服务所使用的启动命令为:
在history中可以发现app.js在被平凡的运行,而且它占用的是80端口
node app.js & //node是nodejs运行代码的代码的命令,&是在后台运行
使用netstat -napt就可以只看到80端口正在被node占用
17.经分析,该服务对于请求来源IP的处理依据是:根据请求源IP地址的第(三)位进行判断【标准格式:9】
/**
* 反向代理
*
*/
module.exports = function(_brain, _app) {
/* INCLUDE */
const path = _brain.A.path;
const async = _brain.A.async;
const proxy = require('http-proxy-middleware');
const net = require('net');
/* DEFINE */
const _tag = path.basename(__filename, ".js");
var _isBanned = false;
var _isStarted = false;
if(!_brain.A.checkIsNull(_brain.C.autorun_config[_tag], _tag)){
_isStarted = _brain.C.autorun_config[_tag];
}
/* DEFINE PROXY */
const _proxy50 = {
protocol: 'http:',
host: '192.168.110.111',
port: 80
}
const _proxy100 = {
protocol: 'http:',
host: '192.168.110.112',
port: 80
}
const _proxy100p = {
protocol: 'http:',
host: '192.168.110.113',
port: 80
} //18行到33行的代码定义了三个对象
/* Private Function */
/**
* Service Running
*/
var service = function (){
if(!_isStarted) return;
// proxy middleware options
const _proxyer_chronus = proxy({
target: '/', // target host
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
router: function(req) {
var clientIP = req.get("x-forwarded-for") //46行是一个关键点,程序通过返回的IP数据包的XFF字段来获取IP地址
if (clientIP == undefined) {
clientIP = req.connection.remoteAddress
} //49行将接收到的IP以点分割成四段,进入下面的判断
var clientIPArr = clientIP.split(".")
if (clientIPArr.length == 4) {
var clientIP3Int = parseInt(clientIPArr[2]) //52定义一个变量,值从分段后的第三段获得
global.logger.warn('[Proxy_RequestHeader] -> ' + JSON.stringify(req.headers));
global.logger.warn('[Proxy_ClientIP] -> ' + clientIP);
if (clientIP3Int <= 50) {
global.logger.warn('[Proxy_Destination] -> ' + JSON.stringify(_proxy50));
return _proxy50
} else if (clientIP3Int <= 100) {
global.logger.warn('[Proxy_Destination] -> ' + JSON.stringify(_proxy100));
return _proxy100
} else {
global.logger.warn('[Proxy_Destination] -> ' + JSON.stringify(_proxy100p));
return _proxy100p
}
}
}
})
_app.all('/*', _proxyer_chronus);
};
/**
* Service Killing
*/
var serviceKiller = function (){
};
/* Public Function */
/* 返回_tag */
var getTag = function (){
return _tag;
};
/* 判断服务是否开启 */
var isStarted = function (){
return _isStarted;
};
/* 判断服务是否被意外禁止 */
var isBanned = function (){
return _isBanned;
};
/* 服务开关 */
var startServer = function (callBack){
_isStarted = true;
service();
if(callBack)
callBack(100, _tag + ' Started');
};
var stopServer = function (callBack){
_isStarted = false;
serviceKiller();
if(callBack)
callBack(100, _tag + ' Stopped');
};
/* Service AutoRun */
if(_isStarted){
startServer();
}else{
stopServer();
}
return{
getTag : getTag,
isStarted : isStarted,
isBanned : isBanned,
startServer : startServer,
stopServer : stopServer,
};
}
从这里我们就可以判断此程序是通过源地址的第三位来进行判断
18.经分析,当判断条件小于50时,服务器会将该请求转发到IP为()的服务器上【标准格式:111.111.111.111】
这里依旧是对上述代码进行分析,小于50对应的是对象“_proxy50”,对应的IP是'192.168.110.111'
19.分析,该服务器转发的目标服务器一共有几台【标准格式:9】
根据上述代码的条件可以得出目标服务器是三台
20.请分析,受害者通讯录被获取时,其设备的IP地址为【标准格式:111.111.111.111】
如果仔细观察history的历史命令可以发现honglianjingsai目录下是有日志文件的并且还被查看过
已知案发时间实在4月24日,我们cd过去,ls可以发现当天的日志只有一个
查看日志后发现当天被转发的IP总共有三个,
192.168.110.142
192.168.110.252
192.168.110.203
一开始这个题根据现有信息是做不了的,但做到后面,我们一旦确定了案发的准确时间(精确到分秒)就可以找到ip
21.请分析,受害者的通讯录被窃取之后,经由该服务器转发到了IP为()的服务器上【标准格式:111.111.111.111】
这题还是是通过查日志
还是根据之前的代码进行分析,我们都可以知道转发的服务器是:192.168.110.113
检材三分析:
22.检材三的原始硬盘的SHA256值为:
老套路,但这里有坑,这三个服务器是负载均衡转发的三个目标服务器,目前已知服务器所转发的对象,是第三个服务器,所以我们要算的是第三台服务器的ip
23.请分析第21题中,所指的服务器的开机密码为:
通过火眼证据分析可以看到shell,里面有密码的记录
24.嫌疑人架设网站使用了宝塔面板,请问面板的登陆用户名为:hl123
确定是web3镜像之后,直接仿真按照之前的配网方法拿到虚拟局域网vmnet1,就可以直接用了
直接在浏览器输入内网面板地址,在登录界面会遇到一个问题,其密码是错误的,这里有两种方法:
方法一:bt,输入5,输入想要修改的密码
方法二:输入命令
cd /www/server/panel && python tools.py panel 123456
25.请分析用于重置宝塔面板密码的函数名为 set_panel_pwd
这题的分析思路在于tool.py这个脚本,可以看到上一题的方法二中修改密码的命令调用的起始页是tools.py这个脚本导出来做代码审计
可以发现tools.py里面对应的是bt命令下的所有功能,下面是import包含的库
import sys,os
panelPath = '/www/server/panel/'
os.chdir(panelPath) //将当前工作目录切换到指定路径
sys.path.insert(0,panelPath + "class/") //sys.path模块可以动态修改系统路径
import public,time,json
if sys.version_info[0] == 3: raw_input = input
我们主要需要关注的是设置面板密码的部分:
在第5行可以看到明文password被md5加密后传到public.password_salt函数中
#设置面板密码
def set_panel_pwd(password,ncli = False):
import db //这里调用了在class目下db模块
sql = db.Sql()
result = sql.table('users').where('id=?',(1,)).setField('password',public.password_salt(public.md5(password),uid=1))
username = sql.table('users').where('id=?',(1,)).getField('username')
if ncli:
print("|-用户名: " + username)
print("|-新密码: " + password)
else:
print(username)
class下的public模块,在tools.py中被调用的模块代码
def md5(strings):
return Md5(strings)
def password_salt(password,username=None,uid=None):
'''
@name 为指定密码加盐
@author hwliang<2020-07-08>
@param password string(被md5加密一次的密码)
@param username string(用户名) 可选
@param uid int(uid) 可选
@return string
'''
chdck_salt()
if not uid:
if not username:
raise Exception('username或uid必需传一项')
uid = M('users').where('username=?',(username,)).getField('id')
salt = M('users').where('id=?',(uid,)).getField('salt')
return md5(md5(password+'_bt.cn')+salt)
public中的调用的函数
def chdck_salt(): //此函数描述了盐的生成方式
'''
@name 检查所有用户密码是否加盐,若没有则自动加上
@author hwliang<2020-07-08>
@return void
'''
if not M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'users','%salt%')).count():
M('users').execute("ALTER TABLE 'users' ADD 'salt' TEXT",())
u_list = M('users').where('salt is NULL',()).field('id,username,password,salt').select()
if isinstance(u_list,str):
if u_list.find('no such table: users') != -1:
rep_default_db()
if not M('sqlite_master').where('type=? AND name=? AND sql LIKE ?', ('table', 'users','%salt%')).count():
M('users').execute("ALTER TABLE 'users' ADD 'salt' TEXT",())
u_list = M('users').where('salt is NULL',()).field('id,username,password,salt').select()
for u_info in u_list:
salt = GetRandomString(12) #12位随机
pdata = {}
pdata['password'] = md5(md5(u_info['password']+'_bt.cn') + salt)
pdata['salt'] = salt
M('users').where('id=?',(u_info['id'],)).update(pdata)
调用了rep_default_db模块,里面调用了文件
def rep_default_db():
db_path = '/www/server/panel/data/'
db_file = db_path + 'default.db'
db_tmp_backup = db_path + 'default_' + format_date("%Y%m%d_%H%M%S") + ".db"
panel_backup = '/www/backup/panel'
bak_list = os.listdir(panel_backup)
if not bak_list: return False
bak_list = sorted(bak_list,reverse=True)
db_bak_file = ''
for d_name in bak_list:
db_bak_file = panel_backup + '/' + d_name + '/data/default.db'
if not os.path.exists(db_bak_file): continue
if os.path.getsize(db_bak_file) < 17408: continue
break
if not db_bak_file: return False
ExecShell("\cp -arf {} {}".format(db_file,db_tmp_backup))
ExecShell("\cp -arf {} {}".format(db_bak_file,db_file))
return True
26.请分析宝塔面板登陆密码的加密方式所使用的哈希算法为 md5
分析上述代码可知
27.请分析宝塔面板对于其默认用户的密码一共执行了几次上题中的哈希算法
三次
28.请分析当前宝塔面板密码加密过程中所使用的salt值为【区分大小写】v87ilhAVumZL
通过SQLite查看文件写入的db文件的users表可以获得答案
29.请分析该服务器,网站源代码所在的绝对路径为/www/wwwroot/www.honglian7001
30.请分析,网站所使用的数据库位于IP为(192.168.110.115)的服务器上(请使用该IP解压检材五,并重构网站)【标准格式:111.111.111.111】
31.请分析,数据库的登陆密码为【区分大小写】 wxrM5GtNXk5k5EPX
看上图
题目要求重构网站,我们直接在宝塔上运行发现没有连接数据库,所以我们主要目标是连接数据库,而数据库的文件可以看到是三个raid文件,raid重组:
通过ufs可以快速算出raid的参数,操作如下:
打开文件选中那三个原始镜像文件:
open就行
依次选中加入raid
直接用取证大师将这些参数在raid重组时填写进去
导出后就可以直接用仿真软件做成虚拟机文件
重构成功后我们打开网址进行测试,可以发现已经连接成功
但是当我们用premium连接数据库的时候却报错了,这里是出题人设置的坑,他建了一个空用户导致我们连接异常,但我们可以直接进入服务器后台修改my.cnf。在后面加上命令
skip-grant-tables
作用是跳过密码检验
然后重启数据库
systemctl restart mysqld
此时直接用数据库软件连接就可以了,根据之前做题可以知道
账号:www_honglian7001
密码:wxrM5GtNXk5k5EPX
32.请尝试重构该网站,并指出,该网站的后台管理界面的入口为/admin【标准格式:/web】
可以尝试对审计网站源代码,也可以查看取证软件中的历史记录或日志看该网页的访问记录
33.已该涉案网站代码中对登录用户的密码做了加密处理。请找出加密算法中的salt值【区分大
小写】lshi4AsSUrUOwWV
34.请分析该网站的管理员用户的密码为:
这个题目的做法有点怪异官方的出题人是说把整个目录都导出来,然后直接用vs对整个目录进行搜索,索索的关键字为“password”。
首先xftp导出整个目录
然后丢到vscode里面
然后直接用搜索功能,可以看到有好几个日志,修改了很多次密码,但最后一次改成了,security
此时我们可以知道
账号:admin
密码:security
补充知识点:
当我们找不到密码时也是可以登入后台的,方法是通过数据库软件找到admin对应的密码位置
根据33题我们知道了密码的加密方式,那我们就可以用自己的密码,来进行同样的加密之后替换原表的值来达到密码的绕过,
可以看到密码已经绕过成功了
35.在对后台账号的密码加密处理过程中,后台一共计算几次哈希值3
36.请统计,后台中,一共有多少条设备记录 6002
37.请通过后台确认,本案中受害者的手机号码为 15611228877
这个题需要结合检材四中的手机来确定受害者的手机型号从而来确定受害手机
38.请分析,本案中受害者的通讯录一共有多少条记录
检材四分析:
通过对检材二和三进行分析,警方通过IP落地,警方成功抓获犯罪嫌疑人,现将嫌疑人的PC机和手机进行了取证,分别制 作了镜像,请使用第13题的答案对检材四进行解密,并回答下列问题
从检材四开始基本就是使用取证大师和火眼证据分析工具来进行分析了
39.请计算检材四-PC的原始硬盘的SHA256值
略
40.请分析,检材四-PC的Bitlocker加密分区的解密密钥为
可以通过取证大师中搜索到
41.请分析,检材四-PC的开机密码为
开机密码的解题思路为找到用户的ntlm值然后放到查md5值的网站直接进行查询
42.经分析发现,检材四-PC是嫌疑人用于管理服务器的设备,其主要通过哪个浏览器控制网站后
这个是使用的取证大师查看浏览器记录
43.请计算PC检材中用户目录下的zip文件的sha256值
略
44.请分析检材四-phone,该手机的IMEI号为
45.请分析检材四-phone,嫌疑人和本案受害者是通过什么软件开始接触的 伊对
之前比赛的时候使用取证大师有些信息没有火眼分析工具全,所以下面的图截的是火眼的
46.请分析检材四-phone,受害者下载恶意APK安装包的地址为 https://cowtransfer.com/s/a6b28b4818904c
这里我们可以进一步的推动剧情,已知受害者下载APP的时间点是4-24 13:24
继续观察聊天记录可以发现4-24 15:02已经获得了通讯录信息
47.请分析检材四-phone,受害者的微信内部ID号为
48.请分析检材四-phone,嫌疑人用于敲诈本案受害者的QQ账号为