Crash on PE import from WS2_32.dll
optimizedaway opened this issue · comments
Target process crashes with access violation during initial remote thread injection:
blink.exe!std::char_traits<char>::length(const char * const _First) Line 462 C++
blink.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign(const char * const _Ptr) Line 2676 C++
blink.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> >(const char * const _Ptr) Line 2185 C++
blink.exe!std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,void *>::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,void *><char const (&)[1],void *,0>(const char[1] & _Val1, void * && _Val2) Line 173 C++
> blink.exe!blink::application::run() Line 74 C++
blink.exe!remote_main(unsigned char * imagebase) Line 101 C++
I debugged target process. Symbols from dxgi.dll and d3d11 are properly initialized, but process fails on access to import->Name
from WS2_32.dll, content of import_name_table[k].u1.AddressOfData looks very suspicious (0x800000000000006f). Addresses from other libraries are OK.
Output from debugger:
_symbols
{ size=0x0000000000000003 }
[hash_function]: hash
[key_eq]: equal_to
[allocator]: allocator
["__ImageBase"]: ("__ImageBase", pbr.exe!0x00007ff65e6a0000)
["CreateDXGIFactory1"]: ("CreateDXGIFactory1", 0x00007ffa0210a200 {dxgi.dll!CreateDXGIFactory1(void)})
["D3D11CreateDevice"]: ("D3D11CreateDevice", 0x00007ffa001d5800 {d3d11.dll!D3D11CreateDevice(void)})
[Raw View]: {...}
(const char *)(_image_base + import_directory_entries[0].Name)
0x00007ff65e84a104 "d3d11.dll"
(const IMAGE_THUNK_DATA *)(_image_base + import_directory_entries[0].Characteristics)
pbr.exe!0x00007ff65e849dd8 {u1={ForwarderString=0x00000000001aa0f0 Function=0x00000000001aa0f0 Ordinal=...} }
u1: {ForwarderString=0x00000000001aa0f0 Function=0x00000000001aa0f0 Ordinal=0x00000000001aa0f0 ...}
(const char *)(_image_base + import_directory_entries[1].Name)
0x00007ff65e84a124 "dxgi.dll"
(const IMAGE_THUNK_DATA *)(_image_base + import_directory_entries[1].Characteristics)
pbr.exe!0x00007ff65e849de8 {u1={ForwarderString=0x00000000001aa10e Function=0x00000000001aa10e Ordinal=...} }
u1: {ForwarderString=0x00000000001aa10e Function=0x00000000001aa10e Ordinal=0x00000000001aa10e ...}
(const char *)(_image_base + import_directory_entries[2].Name)
0x00007ff65e84a14c "WS2_32.dll"
(const IMAGE_THUNK_DATA *)(_image_base + import_directory_entries[2].Characteristics)
pbr.exe!0x00007ff65e849d90 {u1={ForwarderString=0x800000000000006f Function=0x800000000000006f Ordinal=...} }
u1: {ForwarderString=0x800000000000006f Function=0x800000000000006f Ordinal=0x800000000000006f ...}
(const char *)(_image_base + import_directory_entries[3].Name)
0x00007ff65e84a35e "KERNEL32.dll"
(const IMAGE_THUNK_DATA *)(_image_base + import_directory_entries[4].Characteristics)
pbr.exe!0x00007ff65e849b88 {u1={ForwarderString=0x00000000001aa65e Function=0x00000000001aa65e Ordinal=...} }
u1: {ForwarderString=0x00000000001aa65e Function=0x00000000001aa65e Ordinal=0x00000000001aa65e ...}
...
I "fixed" the problem by ignoring symbol addresses with highest bit set:
// Ignore symbol if MSB set in RVA, todo 32bit, ordinal lookup?
if ((import_name_table[k].u1.AddressOfData & 0x8000000000000000) == 0)
{
const auto import = reinterpret_cast<const IMAGE_IMPORT_BY_NAME *>(_image_base + import_name_table[k].u1.AddressOfData);
_symbols.insert({ import->Name, reinterpret_cast<void *>(import_address_table[k].u1.AddressOfData) });
}
I tried to dig through PE spec but didn't find anything useful. Maybe this is a lookup by ordinal number? Any ideas?
Win10 x64 Pro v1803 (17134.471), Windows SDK 10.0.17763.0
Yup, those are imports by ordinals. Not commonly used anymore, but ws2_32.dll is an exception. Will try and figure out a way to get from ordinals back to a symbol name (since that would be necessary to link in modified source code files which reference any functions from ws2_32.dll).