这个np控件会在“确认收货”按钮里用到。点了后会出现6个格子,要填入密码。但mb一到这就会崩溃在
npObjectGetProperty的npObject->_class->getProperty(npObject, identifier, &result)
没办法,只能逆向下这个dll。
其实原因很简单,dll的setwindow_1000128C里会调用 CreateWindow_1000197D创建隐藏的windows
char __thiscall CreateWindow_1000197D(LONG dwNewLong, int npWindow)
{
LONG v2; // esi@1
char result; // al@2
HWND v4; // eax@3
int v5; // eax@4
int v6; // ecx@4
HWND v7; // eax@8
HWND v8; // ST2C_4@8
LONG v9; // eax@10
HWND v10; // ST24_4@10
LONG v11; // eax@10
HWND v12; // ST24_4@10
int v13; // eax@10
struct tagRECT Rect; // [sp+Ch] [bp-10h]@4
v2 = dwNewLong;
if ( npWindow && (v4 = *(HWND *)npWindow, *(_DWORD *)(dwNewLong + 104) = *(_DWORD *)npWindow, v4) )
{
GetClientRect(v4, &Rect);
v5 = Rect.right - Rect.left;
v6 = Rect.bottom - Rect.top;
if ( Rect.right == Rect.left )
v5 = *(_DWORD *)(npWindow + 12);
if ( Rect.bottom == Rect.top )
v6 = *(_DWORD *)(npWindow + 16);
v7 = CreateWindowExA(
0x200u,
"EDIT",
WindowName,
0x56810080u,
Rect.left,
Rect.top,
v5,
v6,
*(HWND *)(v2 + 104),
0,
0,
0);
v8 = *(HWND *)(v2 + 104);
*(_DWORD *)(v2 + 20) = v7;
SetParent(v7, v8);
SendMessageA(*(HWND *)(v2 + 20), 0xC5u, *(_DWORD *)(v2 + 44), 0);
if ( *(_DWORD *)(v2 + 32) )
SendMessageA(*(HWND *)(v2 + 20), 0xCCu, 0x2Au, 0);
v9 = SetWindowLongA(*(HWND *)(v2 + 20), -4, (LONG)hook_win_proc_1000178A);
v10 = *(HWND *)(v2 + 104);
::dwNewLong = (WNDPROC)v9;
v11 = SetWindowLongA(v10, -4, (LONG)sub_10001680);
v12 = *(HWND *)(v2 + 20);
dword_1008E54C = v11;
SetWindowLongA(v12, -21, v2);
SetWindowLongA(*(HWND *)(v2 + 104), -21, v2);
v13 = init_this_24_10037264();
*(_DWORD *)(v2 + 24) = v13;
sub_100366C7(v13);
sub_10036216(*(_DWORD *)(v2 + 24));
sub_100358FD(*(_DWORD *)(v2 + 24));
sub_10004340(*(_DWORD *)(v2 + 24));
sub_10034FCC(*(_DWORD *)(v2 + 24), "支付宝安全控件 Gecko/win32 aliedit/1,2,0,2");
sub_10035314(*(_DWORD *)(v2 + 24), -10002, "alieditversion");
sub_10006254(*(_DWORD *)(v2 + 24));
*(_DWORD *)(v2 + 4) = npWindow;
*(_BYTE *)(v2 + 12) = 1;
result = 1;
}
else
{
result = 0;
}
return result;
}
signed int __cdecl setwindow_1000128C(LONG *a1, int npWindow)
{
LONG v3; // edi@5
if ( !a1 )
return 2;
if ( !npWindow )
return 1;
v3 = *a1;
if ( !*a1 )
return 1;
if ( !sub_10001717(*a1) )
{
if ( !*(_DWORD *)npWindow )
goto LABEL_12;
if ( !CreateWindow_1000197D(v3, npWindow) )
{
sub_10001D3F(v3);
operator delete((void *)v3);
return 4;
}
}
if ( *(_DWORD *)npWindow )
goto LABEL_13;
LABEL_12:
if ( !sub_10001717(v3) )
{
LABEL_13:
sub_10001717(v3);
if ( !*(_DWORD *)npWindow )
sub_10001717(v3);
}
return 0;
}
其中问题就在init_this_24_10037264里,这里会初始化NPObject* npObject附带的一个结构体里的另外个
结构体A(+24偏移),这个会在
int __cdecl crash_1_10034A84(int a1, int a2)
{
int result; // eax@1
int v3; // ecx@2
int v4; // esi@3
result = a1;
if ( a2 < 0 )
{
*(_DWORD *)(a1 + 8) += 8 * a2 + 8;
}
else
{
v3 = 8 * a2;
if ( *(_DWORD *)(a1 + 8) < (unsigned int)(8 * a2 + *(_DWORD *)(a1 + 0xC)) )
{
do
{
*(_DWORD *)(*(_DWORD *)(a1 + 8) + 4) = 0;
v4 = *(_DWORD *)(a1 + 12);
*(_DWORD *)(a1 + 8) += 8;
}
while ( *(_DWORD *)(a1 + 8) < (unsigned int)(v3 + v4) );
}
*(_DWORD *)(a1 + 8) = v3 + *(_DWORD *)(a1 + 12);
}
return result;
}
里用到,而这个函数是在
int __thiscall crash_2_10002320(int this, int a2)
{
int v2; // esi@1
HWND hWnd; // ST0C_4@1
HWND hWnd_1; // ST0C_4@3
char *v5; // eax@4
int v6; // eax@6
char *v7; // eax@9
char *v8; // eax@11
char *v9; // eax@15
int v11; // [sp+Ch] [bp-90h]@6
int v12; // [sp+28h] [bp-74h]@1
int v13; // [sp+2Ch] [bp-70h]@1
char v14; // [sp+30h] [bp-6Ch]@16
char *v15; // [sp+34h] [bp-68h]@4
unsigned int v16; // [sp+48h] [bp-54h]@4
LPARAM lParam; // [sp+4Ch] [bp-50h]@3
int v18; // [sp+98h] [bp-4h]@3
v2 = this;
hWnd = *(HWND *)(this + 20);
v13 = a2;
v12 = 0;
if ( (unsigned int)SendMessageA(hWnd, 0xEu, 0, 0) < 0x40 )// WM_GETTEXTLENGTH
{
memset(&lParam, 0, 0x40u);
hWnd_1 = *(HWND *)(v2 + 20);
*(_BYTE *)(v2 + 28) = 1;
SendMessageA(hWnd_1, 0xDu, 0x3Fu, (LPARAM)&lParam);// WM_GETTEXT
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,std::allocator<char>>((char *)&lParam);
v18 = 0;
if ( *(_DWORD *)(v2 + 32) )
{
v5 = v15;
if ( v16 < 0x10 )
v5 = (char *)&v15;
v6 = sub_10002231((int)&v11, v5);
LOBYTE(v18) = 1;
sub_10001D6A(v6, 0, -1);
LOBYTE(v18) = 0;
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Tidy(1, 0);
}
if ( *(_DWORD *)(v2 + 36) )
{
crash_1_10034A84(*(_DWORD *)(v2 + 24), 0);
sub_10035165(*(_DWORD *)(v2 + 24), -10002, "encode");
sub_10034F77(*(_DWORD *)(v2 + 24), *(_DWORD *)(v2 + 40));
if ( *(_DWORD *)(v2 + 72) < 0x10u )
v7 = (char *)(v2 + 52);
else
v7 = *(char **)(v2 + 52);
sub_10034FCC(*(_DWORD *)(v2 + 24), v7);
v8 = v15;
if ( v16 < 0x10 )
v8 = (char *)&v15;
sub_10034FCC(*(_DWORD *)(v2 + 24), v8);
if ( sub_1003554B(*(_DWORD *)(v2 + 24), 3, 1, 0) )
crash_1_10034A84(*(_DWORD *)(v2 + 24), -2);
v9 = (char *)sub_10034E11(*(_DWORD *)(v2 + 24), -1, 0);
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::assign(v9);
crash_1_10034A84(*(_DWORD *)(v2 + 24), -2);
}
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,std::allocator<char>>(&v14);
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Tidy(1, 0);
}
else
{
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,std::allocator<char>>(v13);
}
return sub_1004737E();
}
里被调用到的。
char __thiscall sub_10002492(int this, int a2, int a3)
{
char *v3; // edi@2
void *v4; // eax@2
size_t v5; // eax@4
char result; // al@4
char v7; // [sp+4h] [bp-20h]@2
char *v8; // [sp+8h] [bp-1Ch]@2
int v9; // [sp+18h] [bp-Ch]@2
unsigned int v10; // [sp+1Ch] [bp-8h]@2
*(_DWORD *)a3 = 0;
*(_DWORD *)(a3 + 8) = 0;
if ( a2 == txtData_1008E514 )
{
crash_2_10002320(**(_DWORD **)(this + 12), (int)&v7);
v3 = (char *)((int (__cdecl *)(int))sub_100013D6)(v9 + 1);
v4 = v8;
if ( v10 < 0x10 )
v4 = &v8;
strcpy(v3, (const char *)v4);
*(_DWORD *)a3 = 5;
v5 = strlen(v3);
*(_DWORD *)(a3 + 8) = v3;
*(_DWORD *)(a3 + 12) = v5;
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Tidy(1, 0);
result = 1;
}
else if ( a2 == dword_1008E528 )
{
*(_DWORD *)a3 = 2;
*(_BYTE *)(a3 + 8) = 0;
result = 1;
}
else
{
result = 0;
}
return result;
}
所以现在逻辑就清楚了:
js里去请求“txtData”的值,dll里就发windows消息到隐藏窗口里去取,此时那个结构体A没被初始化。
没初始化的原因是setwindow没被调用。
原因就是mb做了个优化,会异步调用setwindow(在 WebPluginImpl::platformStartAsyn())。
现在把异步改成同步就搞定了