|
通过IDA看 _QMCreateObjectInternal 函数,没过多久就看出了问题所在
在 QMCreatePrivateQueue 中的 ReplaceDNSNameWithNetBiosName 中,没有对输入进行充分检查,wcscat()导致了一个栈溢出。
; int __cdecl ReplaceDNSNameWithNetBiosName(wchar_t *Str, wchar_t *Dest) ?ReplaceDNSNameWithNetBiosName@@YAXPBGPAG@Z proc near
Str= dword ptr 4 Dest= dword ptr 8
push esi push 5Ch ; Ch push [esp+8+Str] ; Str call ds:__imp__wcschr pop ecx mov esi, eax pop ecx push ?g_szMachineName@@3PAGA ; Source push [esp+8+Dest] ; Dest call ds:__imp__wcscpy pop ecx pop ecx push esi ; Source push [esp+8+Dest] ; Dest call ds:__imp__wcscat // 溢出 pop ecx pop ecx pop esi retn ?ReplaceDNSNameWithNetBiosName@@YAXPBGPAG@Z endp 伪代码:
wchar_t *__cdecl ReplaceDNSNameWithNetBiosName(wchar_t *Str, wchar_t *Dest) { wchar_t *v3; // esi@1
v3 = _wcschr(Str, 0x5Cu); _wcscpy(Dest, g_szMachineName); return _wcscat(Dest, v3); } 这里我们后面再回过头来看。
那么,函数调用是这样的:
_QMCreateObjectInternal |---------------QMCreatePrivateQueue |-------------------ReplaceDNSNameWithNetBiosName _QMCreateObjectInternal的伪代码为:
signed int __thiscall QMCreateObjectInternal(struct _RTL_CRITICAL_SECTION *this, RPC_BINDING_HANDLE Binding, unsigned int Type, wchar_t *Str, int a5, int a6, int a7, int a8, int a9) { __int32 v10; // edi@6 __int32 v11; // eax@7 int v12; // ST18_4@9 struct _RTL_CRITICAL_SECTION *v13; // [sp+4h] [bp-10h]@1 int v14; // [sp+10h] [bp-4h]@4
v13 = this; if ( a5 && !a6 ) { LogMsgHR(-1072824314, off_6B27271C, 0x125u); return -1072824314; } v13 = &qmcmd_cs; EnterCriticalSection(&qmcmd_cs); v14 = 0; if ( Type == 1 ) { v12 = 1; goto LABEL_14; } if ( Type == 2 ) { Type = 0; v11 = I_RpcBindingInqTransportType(Binding, &Type); if ( v11 ) goto LABEL_20; if ( Type == 4 ) { v12 = 0; LABEL_14: v10 = CQPrivate__QMCreatePrivateQueue(Str, a5, a6, a7, a8, a9, v12); goto LABEL_15; } if ( v11 ) LABEL_20: LogMsgRPCStatus(v11, off_6B27271C, 0x28u); LeaveCriticalSection(&qmcmd_cs); return -1072824283; } v10 = -1072824319; LABEL_15: if ( v10 < 0 ) LogMsgHR(v10, off_6B27271C, 0x32u); LeaveCriticalSection(&qmcmd_cs); return v10; } ============= 这是华丽的分割线 ================
首先要调用到 QMCreatePrivateQueue .
我们看到以下是依次是 _QMCreateObjectInternal的六个参数 Type= dword ptr 0Ch Str= dword ptr 10h arg_C= dword ptr 14h arg_10= dword ptr 18h arg_14= dword ptr 1Ch arg_18= dword ptr 20h arg_1C= dword ptr 24h
看以下代码片段
loc_6B22555B: ; CCriticalSection qmcmd_cs mov esi, offset ?qmcmd_cs@@3VCCriticalSection@@A push esi ; lpCriticalSection mov [ebp+var_10], esi call ds:__imp__EnterCriticalSection@4 ; EnterCriticalSection(x) mov eax, [ebp+Type] mov [ebp+var_4], ebx dec eax jz short loc_6B2255C1
在代码中,如果eax为1,dec eax后条件为真,会跳转到QMCreatePrivateQueue 去执行
而eax是由mov eax, [ebp+Type]传入的
所以要让流程走到QMCreatePrivateQueue _QMCreateObjectInternal的第一个参数必须是为0x00000001
上一页 [1] [2] [3] [4] [5] [6] 下一页 |