У нас есть sandbox.exe, app.exe и app.dll. Если пользователи хотят запустить приложение, не изолированное в песочнице, они запускают app.exe. Если пользователи хотят запустить приложение в «песочнице», они запускают sandbox.exe, который загружает app.dll. См., например, загрузочное приложение chrome.exe, которое загружает chrome.dll.
Теперь мы хотим уменьшить количество распространяемых файлов, удалить app.dll и LoadLibraryA("app.exe").
Известно, что
Если указанный модуль является исполняемым модулем, статический импорт не загружается; вместо этого модуль загружается, как если бы это был LoadLibraryEx, с флагом DONT_RESOLVE_DLL_REFERENCES.
Итак, мы загружаем исполняемый модуль, загружаем ссылки на его dll, инициализируем IAT (таблицу адресов импорта) и вызываем WinMainCRTStartup(nullptr) в экспортированной функции dll, которая вызывается sandbox.exe. Загруженное приложение работает нормально до тех пор, пока не потребуется инициализировать локальную статическую переменную.
int F() {
static const int ret = GetLastError() + 1; // non zero value
return ret;
}
Дизассемблирование неоптимизированного инициализатора:
int F() {
00007FF7C27EA680 push rdi
00007FF7C27EA682 sub rsp,60h
00007FF7C27EA686 lea rdi,[rsp+40h]
00007FF7C27EA68B mov ecx,8
00007FF7C27EA690 mov eax,0CCCCCCCCh
00007FF7C27EA695 rep stos dword ptr [rdi]
00007FF7C27EA697 lea rcx,[__8398B9A9_core-win@cc (07FF7C3033B4Dh)]
00007FF7C27EA69E call __CheckForDebuggerJustMyCode (07FF7C239D00Ch)
static const int ret = GetLastError() + 1; // non zero value
00007FF7C27EA6A3 mov eax,18Ch
00007FF7C27EA6A8 mov eax,eax
00007FF7C27EA6AA mov ecx,dword ptr [_tls_index (07FF7C2FA4C7Ch)]
00007FF7C27EA6B0 mov rdx,qword ptr gs:[58h]
00007FF7C27EA6B9 mov rcx,qword ptr [rdx+rcx*8]
00007FF7C27EA6BD mov eax,dword ptr [rax+rcx]
00007FF7C27EA6C0 cmp dword ptr [$TSS0 (07FF7C2FA2500h)],eax
00007FF7C27EA6C6 jle F+77h (07FF7C27EA6F7h)
00007FF7C27EA6C8 lea rcx,[$TSS0 (07FF7C2FA2500h)]
00007FF7C27EA6CF call _Init_thread_header (07FF7C2399D80h)
00007FF7C27EA6D4 cmp dword ptr [$TSS0 (07FF7C2FA2500h)],0FFFFFFFFh
00007FF7C27EA6DB jne F+77h (07FF7C27EA6F7h)
00007FF7C27EA6DD call qword ptr [__imp_GetLastError (07FF7C301D110h)]
00007FF7C27EA6E2 inc eax
00007FF7C27EA6E4 mov dword ptr [ret (07FF7C2FA24FCh)],eax
00007FF7C27EA6EA lea rcx,[$TSS0 (07FF7C2FA2500h)]
00007FF7C27EA6F1 call _Init_thread_footer (07FF7C239AA87h)
00007FF7C27EA6F6 nop
По неизвестной причине eax получает 0, а $TSS0 — правильный 0 при первом cmp. Таким образом, 0 Name);
if (!pszModName)
break;
IATRESULTS::MODULEINFO m;
m.name = pszModName;
HINSTANCE hImportDLL = LoadLibraryA(pszModName);
if (!hImportDLL) {
m.f = IATRESULTS::FAILUREREASON::NOTFOUND;
res.modules.push_back(m);
continue;
}
m.handle = hImportDLL;
m.f = IATRESULTS::FAILUREREASON::SUCCESS;
// Get caller's import address table (IAT) for the callee's functions
PIMAGE_THUNK_DATA pThunk =
(PIMAGE_THUNK_DATA)((PBYTE)h + pImportDesc->FirstThunk);
// Replace current function address with new function address
for (; pThunk->u1.Function; pThunk++) {
IATRESULTS::FUNCTIONINFO fu;
FARPROC pfnNew = 0;
size_t rva = 0;
#ifdef _WIN64
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
#else
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
#endif
{
// Ordinal
#ifdef _WIN64
size_t ord = IMAGE_ORDINAL64(pThunk->u1.Ordinal);
#else
size_t ord = IMAGE_ORDINAL32(pThunk->u1.Ordinal);
#endif
fu.ord = ord;
m.functions.push_back(fu);
PROC* ppfn = (PROC*)&pThunk->u1.Function;
if (!ppfn) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
rva = (size_t)pThunk;
pfnNew = GetProcAddress(hImportDLL, (LPCSTR)ord);
if (!pfnNew) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
} else {
// Get the address of the function address
PROC* ppfn = (PROC*)&pThunk->u1.Function;
if (!ppfn) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
rva = (size_t)pThunk;
PSTR fName = (PSTR)h;
fName += pThunk->u1.Function;
fName += 2;
if (!fName)
break;
fu.name = fName;
pfnNew = GetProcAddress(hImportDLL, fName);
if (!pfnNew) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
}
// Patch it now...
auto hp = GetCurrentProcess();
if (!WriteProcessMemory(hp, (LPVOID*)rva, &pfnNew, sizeof(pfnNew),
NULL) &&
(ERROR_NOACCESS == GetLastError())) {
DWORD dwOldProtect;
if (VirtualProtect((LPVOID)rva, sizeof(pfnNew), PAGE_WRITECOPY,
&dwOldProtect)) {
if (!WriteProcessMemory(GetCurrentProcess(), (LPVOID*)rva, &pfnNew,
sizeof(pfnNew), NULL)) {
fu.f = IATRESULTS::FAILUREREASON::CANNOTPATCH;
continue;
}
if (!VirtualProtect((LPVOID)rva, sizeof(pfnNew), dwOldProtect,
&dwOldProtect)) {
fu.f = IATRESULTS::FAILUREREASON::CANNOTPATCH;
continue;
}
}
}
m.functions.push_back(fu);
}
res.modules.push_back(m);
}
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
CoInitializeEx(0, 0);
HINSTANCE hL = LoadLibrary(L"app.exe");
if (!hL)
return 0;
IATRESULTS res;
ParseIAT(hL, res);
auto* run_win_main = (void(WINAPI*)())GetProcAddress(hL, "RunWinMain");
if (!run_win_main)
return 0;
run_win_main();
return 0;
}
#pragma comment(lib, "dbghelp.lib")
app.cc
#include
int F() {
static const int ret = GetLastError() + 1; // non zero value
return ret;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
return F();
}
extern "C" void WinMainCRTStartup(LPVOID);
extern "C" __declspec(dllexport) void RunWinMain() {
WinMainCRTStartup(nullptr);
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... ded-as-dll
Локальные статические переменные не инициализируются, если приложение загружается как dll. ⇐ C++
Программы на C++. Форум разработчиков
1760659263
Anonymous
У нас есть sandbox.exe, app.exe и app.dll. Если пользователи хотят запустить приложение, не изолированное в песочнице, они запускают app.exe. Если пользователи хотят запустить приложение в «песочнице», они запускают sandbox.exe, который загружает app.dll. См., например, загрузочное приложение chrome.exe, которое загружает chrome.dll.
Теперь мы хотим уменьшить количество распространяемых файлов, удалить app.dll и LoadLibraryA("app.exe").
Известно, что
Если указанный модуль является исполняемым модулем, статический импорт не загружается; вместо этого модуль загружается, как если бы это был LoadLibraryEx, с флагом DONT_RESOLVE_DLL_REFERENCES.
Итак, мы загружаем исполняемый модуль, загружаем ссылки на его dll, инициализируем IAT (таблицу адресов импорта) и вызываем WinMainCRTStartup(nullptr) в экспортированной функции dll, которая вызывается sandbox.exe. Загруженное приложение работает нормально до тех пор, пока не потребуется инициализировать локальную статическую переменную.
int F() {
static const int ret = GetLastError() + 1; // non zero value
return ret;
}
Дизассемблирование неоптимизированного инициализатора:
int F() {
00007FF7C27EA680 push rdi
00007FF7C27EA682 sub rsp,60h
00007FF7C27EA686 lea rdi,[rsp+40h]
00007FF7C27EA68B mov ecx,8
00007FF7C27EA690 mov eax,0CCCCCCCCh
00007FF7C27EA695 rep stos dword ptr [rdi]
00007FF7C27EA697 lea rcx,[__8398B9A9_core-win@cc (07FF7C3033B4Dh)]
00007FF7C27EA69E call __CheckForDebuggerJustMyCode (07FF7C239D00Ch)
static const int ret = GetLastError() + 1; // non zero value
00007FF7C27EA6A3 mov eax,18Ch
00007FF7C27EA6A8 mov eax,eax
00007FF7C27EA6AA mov ecx,dword ptr [_tls_index (07FF7C2FA4C7Ch)]
00007FF7C27EA6B0 mov rdx,qword ptr gs:[58h]
00007FF7C27EA6B9 mov rcx,qword ptr [rdx+rcx*8]
00007FF7C27EA6BD mov eax,dword ptr [rax+rcx]
00007FF7C27EA6C0 cmp dword ptr [$TSS0 (07FF7C2FA2500h)],eax
00007FF7C27EA6C6 jle F+77h (07FF7C27EA6F7h)
00007FF7C27EA6C8 lea rcx,[$TSS0 (07FF7C2FA2500h)]
00007FF7C27EA6CF call _Init_thread_header (07FF7C2399D80h)
00007FF7C27EA6D4 cmp dword ptr [$TSS0 (07FF7C2FA2500h)],0FFFFFFFFh
00007FF7C27EA6DB jne F+77h (07FF7C27EA6F7h)
00007FF7C27EA6DD call qword ptr [__imp_GetLastError (07FF7C301D110h)]
00007FF7C27EA6E2 inc eax
00007FF7C27EA6E4 mov dword ptr [ret (07FF7C2FA24FCh)],eax
00007FF7C27EA6EA lea rcx,[$TSS0 (07FF7C2FA2500h)]
00007FF7C27EA6F1 call _Init_thread_footer (07FF7C239AA87h)
00007FF7C27EA6F6 nop
По неизвестной причине eax получает 0, а $TSS0 — правильный 0 при первом cmp. Таким образом, 0 Name);
if (!pszModName)
break;
IATRESULTS::MODULEINFO m;
m.name = pszModName;
HINSTANCE hImportDLL = LoadLibraryA(pszModName);
if (!hImportDLL) {
m.f = IATRESULTS::FAILUREREASON::NOTFOUND;
res.modules.push_back(m);
continue;
}
m.handle = hImportDLL;
m.f = IATRESULTS::FAILUREREASON::SUCCESS;
// Get caller's import address table (IAT) for the callee's functions
PIMAGE_THUNK_DATA pThunk =
(PIMAGE_THUNK_DATA)((PBYTE)h + pImportDesc->FirstThunk);
// Replace current function address with new function address
for (; pThunk->u1.Function; pThunk++) {
IATRESULTS::FUNCTIONINFO fu;
FARPROC pfnNew = 0;
size_t rva = 0;
#ifdef _WIN64
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
#else
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
#endif
{
// Ordinal
#ifdef _WIN64
size_t ord = IMAGE_ORDINAL64(pThunk->u1.Ordinal);
#else
size_t ord = IMAGE_ORDINAL32(pThunk->u1.Ordinal);
#endif
fu.ord = ord;
m.functions.push_back(fu);
PROC* ppfn = (PROC*)&pThunk->u1.Function;
if (!ppfn) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
rva = (size_t)pThunk;
pfnNew = GetProcAddress(hImportDLL, (LPCSTR)ord);
if (!pfnNew) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
} else {
// Get the address of the function address
PROC* ppfn = (PROC*)&pThunk->u1.Function;
if (!ppfn) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
rva = (size_t)pThunk;
PSTR fName = (PSTR)h;
fName += pThunk->u1.Function;
fName += 2;
if (!fName)
break;
fu.name = fName;
pfnNew = GetProcAddress(hImportDLL, fName);
if (!pfnNew) {
fu.f = IATRESULTS::FAILUREREASON::NOTFOUND;
m.functions.push_back(fu);
continue;
}
}
// Patch it now...
auto hp = GetCurrentProcess();
if (!WriteProcessMemory(hp, (LPVOID*)rva, &pfnNew, sizeof(pfnNew),
NULL) &&
(ERROR_NOACCESS == GetLastError())) {
DWORD dwOldProtect;
if (VirtualProtect((LPVOID)rva, sizeof(pfnNew), PAGE_WRITECOPY,
&dwOldProtect)) {
if (!WriteProcessMemory(GetCurrentProcess(), (LPVOID*)rva, &pfnNew,
sizeof(pfnNew), NULL)) {
fu.f = IATRESULTS::FAILUREREASON::CANNOTPATCH;
continue;
}
if (!VirtualProtect((LPVOID)rva, sizeof(pfnNew), dwOldProtect,
&dwOldProtect)) {
fu.f = IATRESULTS::FAILUREREASON::CANNOTPATCH;
continue;
}
}
}
m.functions.push_back(fu);
}
res.modules.push_back(m);
}
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
CoInitializeEx(0, 0);
HINSTANCE hL = LoadLibrary(L"app.exe");
if (!hL)
return 0;
IATRESULTS res;
ParseIAT(hL, res);
auto* run_win_main = (void(WINAPI*)())GetProcAddress(hL, "RunWinMain");
if (!run_win_main)
return 0;
run_win_main();
return 0;
}
#pragma comment(lib, "dbghelp.lib")
app.cc
#include
int F() {
static const int ret = GetLastError() + 1; // non zero value
return ret;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
return F();
}
extern "C" void WinMainCRTStartup(LPVOID);
extern "C" __declspec(dllexport) void RunWinMain() {
WinMainCRTStartup(nullptr);
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79791868/local-static-variables-are-not-initialized-if-app-is-loaded-as-dll[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия