最近在分析某公司DLP产品,里边文档控制相关功能,出于好奇分析了一下原理。
应用层的权限控制一般通过全局Hook注入DLL进行权限控制,使用工具PCHunder发现,除了WH_KEYBOARD_LL消息Hook,没有其它消息Hook,最后通过PCHunder发现是通过驱动层进行设置PsSetCreateProcessNotifyRoutine回调注入Shellcode实现。
具体IDA分析如下图:
bool __stdcall sub_15D40(HANDLE ProcessHandle, wchar_t *wzDllPath)
{
int v3; // [sp+0h] [bp-488h]@21
int v4; // [sp+4h] [bp-484h]@11
char v5; // [sp+8h] [bp-480h]@11
int v6; // [sp+14h] [bp-474h]@12
int v7; // [sp+18h] [bp-470h]@13
unsigned __int8 v8; // [sp+240h] [bp-248h]@2
int v9; // [sp+241h] [bp-247h]@2
unsigned __int8 v10; // [sp+245h] [bp-243h]@2
int v11; // [sp+246h] [bp-242h]@2
unsigned __int16 v12; // [sp+24Ah] [bp-23Eh]@2
int v13; // [sp+24Ch] [bp-23Ch]@2
int v14; // [sp+250h] [bp-238h]@2
int v15; // [sp+254h] [bp-234h]@3
__int16 v16; // [sp+25Dh] [bp-22Bh]@5
__int16 v17; // [sp+25Fh] [bp-229h]@5
int v18; // [sp+261h] [bp-227h]@5
wchar_t v19; // [sp+265h] [bp-223h]@5
int v20; // [sp+46Dh] [bp-1Bh]@5
int v21; // [sp+471h] [bp-17h]@5
unsigned __int8 v22; // [sp+478h] [bp-10h]@8
int v23; // [sp+479h] [bp-Fh]@11
bool v24; // [sp+483h] [bp-5h]@1
int v25; // [sp+484h] [bp-4h]@1
v24 = 0;
v25 = (int)MyAllocateVirtualMemory(ProcessHandle, 0x2BBu, 0);
if ( v25 )
{
v8 = 0xB8u; // MOV EAX,XXXXXXXX
v9 = v25;
v10 = 0xB9u; // MOV ECX,XXXXXXXX
v11 = v25 + 565;
v12 = 0xD1FFu; // CALL ECX
v13 = 0x4C69636D; // 特征码
v14 = 0;
v15 = pfnNtTestAlert ? pfnNtTestAlert : sub_15570(ProcessHandle);
v16 = 2 * wcslen(wzDllPath); // UNICODE_STRING ++0 Length
v17 = v16 + 2; // UNICODE_STRING ++2 MaxmumLength
v18 = v25 + 0x25; // UNICODE_STRING ++4 Buffer
wcscpy(&v19, wzDllPath); // 将wzDllPath拷贝进ShellCode
v20 = pfnNtProtectVirtualMemory;
v21 = pfnLdrLoadDll;
if ( v15 )
{
if ( MyWriteVirtualMemory((int)ProcessHandle, v25, (int)&v8, 566)
&& MyWriteVirtualMemory((int)ProcessHandle, v25 + 0x235, (int)sub_10420, 133)
&& MyReadVirtualMemory((int)ProcessHandle, v15, (int)&v22, 5)// 读取pfnNtTestAlert函数前5个字节备份到ShellCode中
&& MyWriteVirtualMemory((int)ProcessHandle, v25 + 0x18, (int)&v22, 5) )
{
if ( v22 == 0xE9 ) // 构造要插入dll的链表ShellCode
{
v4 = v15 + v23 + 5;
if ( MyReadVirtualMemory((int)ProcessHandle, v4, (int)&v5, 566) && v6 == 0x4C69636D )
{
while ( v7 )
{
v4 = v7;
if ( !MyReadVirtualMemory((int)ProcessHandle, v7, (int)&v5, 566) || v6 != 0x4C69636D )
{
v4 = 0;
break;
}
}
if ( v4 )
{
v7 = v25;
v24 = MyWriteVirtualMemory((int)ProcessHandle, v4, (int)&v5, 566);
}
}
}
if ( !v24 && MyProtectVirutalMemory((int)ProcessHandle, v15, 5, 64, (int)&v3) )// 修改pfnNtTestAlert函数前面5个字节为jmp XXXX,其中XXXX为Shellcode入口地址
{
v22 = 0xE9u;
v23 = v25 - v15 - 5;
MyWriteVirtualMemory((int)ProcessHandle, v15, (int)&v22, 5);
MyProtectVirutalMemory((int)ProcessHandle, v15, 5, v3, (int)&v3);
v24 = 1;
}
}
}
}
return v24;
}
seg000:00000000 seg000 segment byte public 'CODE' use32
seg000:00000000 assume cs:seg000
seg000:00000000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:00000000 mov eax, 40000h
seg000:00000005
seg000:00000005 loc_5:
seg000:00000005 mov ecx, 40235h
seg000:0000000A call ecx
seg000:0000000A ; ---------------------------------------------------------------------------
seg000:0000000C dd 4C69636Dh ; 特征码
seg000:00000010 dd 0 ; 下一个ShellCode地址
seg000:00000014 dd 76EC5D30h ; pfnNtTestAlert
seg000:00000018 ; ---------------------------------------------------------------------------
seg000:00000018 mov eax, 174h
seg000:00000018 ; ---------------------------------------------------------------------------
seg000:0000001D UNICODE_STRING <5Eh, 60h, 40025h>
seg000:00000025 aCProgramFilesM:
seg000:00000025 unicode 0, <C:\Program Files\XXXXX\DLP\Agent\fcagcbh32.dll>,0
....
seg000:0000022D dd 76EC5360h ; pfnNtProtectVirtualMemory
seg000:00000231 dd 76EDF585h ; pfnLdrLoadDll
seg000:00000235
seg000:00000235 ; =============== S U B R O U T I N E =======================================
seg000:00000235
seg000:00000235 ; Attributes: bp-based frame
seg000:00000235
seg000:00000235 sub_235 proc near
seg000:00000235
seg000:00000235 var_C = dword ptr -0Ch
seg000:00000235 var_8 = dword ptr -8
seg000:00000235 var_4 = dword ptr -4
seg000:00000235
seg000:00000235 push ebp
seg000:00000236 mov ebp, esp
seg000:00000238 add esp, 0FFFFFFF4h
seg000:0000023B push ebx
seg000:0000023C mov ebx, eax ; 参数基址
seg000:0000023E mov [ebp+var_4], ebp
seg000:00000241 mov eax, [ebp+var_4]
seg000:00000244 add eax, 4 ; 指向栈上函数返回地址
seg000:00000247 mov edx, [ebx+14h]
seg000:0000024A mov [eax], edx ; 修改函数返回地址为pfnNtTestAlert
seg000:0000024C mov eax, [ebx+14h]
seg000:0000024F mov [ebp+var_C], eax
seg000:00000252 mov [ebp+var_4], 5
seg000:00000259 lea eax, [ebp+var_8]
seg000:0000025C push eax ; OldProtect
seg000:0000025D push 40h ; '@' ; PAGE_EXECUTE_READWRITE
seg000:0000025F lea eax, [ebp+var_4]
seg000:00000262 push eax ; RegionSize
seg000:00000263 lea eax, [ebp+var_C]
seg000:00000266 push eax ; BaseAddress
seg000:00000267 push 0FFFFFFFFh ; ProcessHandle
seg000:00000269 call dword ptr [ebx+22Dh] ; NtProtectVirtualMemory
seg000:0000026F mov eax, [ebx+14h]
seg000:00000272 mov edx, [ebx+18h]
seg000:00000275 mov [eax], edx
seg000:00000277 mov dl, [ebx+1Ch] ; 修改NtTestAlert函数前5个字节为MOV EAX, 174h
seg000:0000027A mov [eax+4], dl
seg000:0000027D mov [ebp+var_4], 5
seg000:00000284 lea eax, [ebp+var_8]
seg000:00000287 push eax ; OldProtect
seg000:00000288 mov eax, [ebp+var_8]
seg000:0000028B push eax ; NewProtectWin32
seg000:0000028C lea eax, [ebp+var_4]
seg000:0000028F push eax ; RegionSize
seg000:00000290 lea eax, [ebp+var_C]
seg000:00000293 push eax ; BaseAddress
seg000:00000294 push 0FFFFFFFFh ; ProcessHandle
seg000:00000296 call dword ptr [ebx+22Dh] ; NtProtectVirtualMemory
seg000:0000029C
seg000:0000029C loc_29C: ; CODE XREF: sub_235+7Ej
seg000:0000029C lea eax, [ebp+var_4]
seg000:0000029F push eax
seg000:000002A0 lea eax, [ebx+1Dh]
seg000:000002A3 push eax
seg000:000002A4 push 0
seg000:000002A6 push 0
seg000:000002A8 call dword ptr [ebx+231h] ; LdrLoadDll
seg000:000002AE mov ebx, [ebx+10h]
seg000:000002B1 test ebx, ebx
seg000:000002B3 jnz short loc_29C
seg000:000002B5 pop ebx
seg000:000002B6 mov esp, ebp
seg000:000002B8 pop ebp
seg000:000002B9 retn
seg000:000002B9 sub_235 endp
seg000:000002B9
seg000:000002B9 ; ---------------------------------------------------------------------------
seg000:000002BA align 1000h
seg000:000002BA seg000 ends
seg000:000002BA
seg000:000002BA
seg000:000002BA end
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)