green Ага, а перед ним стандартный пролог: Код (Text): NtQuerySystemInformation: SEH_Prolog() ... Jmp [DispatchTable + ecx*4] [0]: ... ExpGetSystemBasicInformation() ... ExpGetSystemBasicInformation: SEH_prolog() ... Реально ваша ситуация не нужна.
PSR1257 Ваше решение не работоспособно, так как: 1. Разность SFN исходной и конечной процедур не постоянна. 2. Локальные параметры не постоянны. 3. Адреса не известны.
Clerk Можете сдампить реальный фрейм и я вам составлю сигну к нему? Примерно 20h-40h от RET_ADDR? При применении сигнатуры это разве имеет значение? Мы сканируем стек в поисках фрейма.
PSR1257 Код (Text): Call stack of main thread Address Stack Procedure / arguments Called from Frame 0012F948 7C91C135 Sfc.0040100A ntdll.7C91C12F 0012F9BC 0012F94C 76BE0000 Arg1 = 76BE0000 0012F950 00242078 Arg2 = 00242078 0012F954 00242118 Arg3 = 00242118 0012F9C0 7C91629D ? ntdll._LdrpWalkImportDescriptor@8 ntdll.7C916298 0012F9BC 0012FC70 7C9164B3 ? ntdll._LdrpLoadDll@24 ntdll.7C9164AE 0012FC6C 0012FC74 00000000 Arg1 = 00000000 0012FC78 00142A68 Arg2 = 00142A68 0012FC7C 0012FF60 Arg3 = 0012FF60 0012FC80 0012FF40 Arg4 = 0012FF40 0012FC84 0012FF5C Arg5 = 0012FF5C 0012FC88 00000001 Arg6 = 00000001 0012FF18 7C801BBD ? <jmp.&ntdll.LdrLoadDll> kernel32.7C801BB8 0012FF14 0012FF1C 00142A68 Arg1 = 00142A68 0012FF20 0012FF60 Arg2 = 0012FF60 0012FF24 0012FF40 Arg3 = 0012FF40 0012FF28 0012FF5C Arg4 = 0012FF5C 0012FF80 7C801D72 ? kernel32.LoadLibraryExW kernel32.LoadLibraryExA+1A 0012FF7C 0012FF84 7FFDEC00 FileName = "psapi.dll" 0012FF88 00000000 hFile = NULL 0012FF8C 00000000 Flags = 0 0012FF94 7C801DA8 kernel32.LoadLibraryExA kernel32.LoadLibraryA+28 0012FF90 0012FF98 0040108A FileName = "psapi.dll" 0012FF9C 00000000 hFile = NULL 0012FFA0 00000000 Flags = 0 0012FFB0 00401140 Sfc._LoadLibraryA@4 Sfc.0040113B 0012FFAC 0012FFB4 0040108A FileName = "psapi.dll" 0012FFC4 7C817067 Includes Sfc.00401140 kernel32.7C817064 0012FFC0 ESP 0012F948 EBP 0012F9BC EIP 00401046 Sfc._LdrpManifestProberRoutine@12 http://pastebin.com/1Mm1rQDb
Весь топик не читал. Могу повторить чью-то идею... Решал похожую задачу, искал нужный стековый фрейм путём перебора всех фреймов выше текущего с целью поиска сигнатуры функции (точнее группы сигнатур, т.к. были несколько версий функции). Решение не универсальное, но рабочее для заданных условий. UPD: Сигнатуру искал в коде, т.е. смотрел адрес возврата и "осматривал" его окрестность.
7mm Известно: o Адрес исходной функции, при выходе из которой необходимо получить управление. o Калбэк известен, в нём наш код. Не известно: o Адреса функций. o Вложенность, тоесть число функций. o Адреса возврата в функции.
Clerk Клерк, если говорить про моё решение схожей задачи, то мне нужна была бы какая-нибудь сигнатура исходной функции, рядом с адресом возврата. Код (Text): BOOL HijackStackFrame(PSTACK_FRAME pStackFrame) { ULONG NewEip = pStackFrame->Eip - 4; if (REF_DWORD(NewEip) == MAGIC_SING_1) { for (int i=0; i<64; i++, NewEip--) { if ((REF_DWORD(NewEip) & 0x00FFFFFF) == MAGIC_SIGN_2) { pStackFrame->Eip = NewEip; return TRUE; } } } return FALSE; } VOID SearchForCaller() { PSTACK_FRAME pStackFrame; GET_STACK_FRAME(pStackFrame); while (pStackFrame->Ebp) { if (HijackStackFrame(pStackFrame)) { return; } pStackFrame = (PSTACK_FRAME)pStackFrame->Ebp; } }
Ну вам же в динамике надо, универсально =) Тогда да, моё решение покатит в случае, если получится динамически определять сигнатуру. Мне нужно было в статике всё это решить, т.е. я взял дизасм и выбрал из функции сигнатуру. Только не пойму, почему "сигнатуры не известны, так как не известны адреса возврата"? По-моему, такому подходу похрен на количество и качество промежуточных функций - вы сигнатурой определяете одну единственную, целевую (исходную).
Clerk Спасибо, надеюсь что в короткое время дам ответ. Идейка не новая и опробованная - 7mm к примеру юзал - по всем ощущениям должно прокатить. Не прокатит - так и отпишу.
Clerk Вот пример фильтра: Предполагаем что верхний элемент в данный момент в S (0012F948): Код (Text): 0012F948 7C91C135 ; Элемент принадлежит IB ntdll или даже >>24 == 0x7C. 0012F94C 76BE0000 ; Тут наверное 0xFFFF == 0x0000, надо экспериментировать 0012F950 00242078 ; Нужно знать что это, но уже можно >>24 == 0x00 0012F954 00242118 ; Нужно знать что это, но уже можно >>24 == 0x00 ; Возможно также S[i-0x10]&0xFFFF0000 == S[i-0x0C]&0xFFFF0000 0012F9C0 7C91629D ; -14h Элемент принадлежит IB ntdll 0012FC70 7C9164B3 ; -18h Элемент принадлежит IB ntdll 0012FC74 00000000 ; -1Ch Просто == 0x0000000 или (если счетчик) &0xFF == 0 0012FC78 00142A68 ; -20h ?? 0012FC7C 0012FF60 ; -24h Возможно (S[i-24h]-S[i-28h]) == 0x20, также S[i-24h] и S[i-28h] принадлежит стеку. 0012FC80 0012FF40 ; -28h 0012FC84 0012FF5C ; -2Ch 0012FC88 00000001 ; == 00000001 ... Ну и так далее. PS Как указал 7mm, можно также ходить по предполагаемым адресам в стеке - если это ссылка на конкретный код в Ntdll, то (код вряд ли сильно плавает) это также может быть куском сигны.
PSR1257 Я бы смотрел не абсолютные значения в адресов в стеке, а, например, разности между адресами и вершиной. UPD: Кстати говоря, вектор таких значений может с достаточной степенью точности идентифицировать целевую функцию.
7mm Да-да, это я как пример указал - нужно абстрагироваться от конкретного положения модулей в памяти. Допустим если я пишу "адрес принадлежит IB Ntdll", то это имеется в виду для текущей машины и он получен заранее.
Clerk Т.е. под "универсальным" Вы подразумеваете решение, которое работает в пределах системного кода windows определённых версий? Тогда вопросов нет...
Всем. Вот вы предлагаете всякое фуфло. Мой семпл лежит выше, он позволяет решить абсолютно любую в NT подобную задачу(я есчо не сталкивался с теми, которые не могбы посредством этого решить). Ваши способы унылы, сигнатуры там какието не рабочие и прочая ахинея. Семпл в студию.
Клерк, может я чего-то не понимаю. Есть условие: - Дана некая целевая функция X, причём её адрес известен. - Известно также, что в процессе своей работы эта функция вызывает некий колбэк - Y, наш колбэк. Требуется из колбэка Y изменить поведение потока таким образом, чтобы получить управление при возврате в X. Так?.. Тогда, последовательность вызовов будет следующая: Код (Text): SomeFunction -> X -> A1 -> A2 -> ... -> An -> Y При этом, в стеке будет сформирована следующая цепочка стековых фреймов: Код (Text): [SomeFunction(EIP), EBP] -> [X(EIP), EBP] -> [A1(EIP), EBP] -> [A2(EIP), EBP] -> ... [An(EIP), EBP] Вся сложность заключается в том, каким образом идентифицировать целевую функцию X, т.е. как определить, что адрес X(EIP), лежащий в стековом фрейме [X(EIP), EBP] принадлежит именно функции X? В этом вся проблема что ли?.. Ну так вам было предложено минимум несколько путей решения этой задачи. Один с использованием кодовых сигнатур, другой - с использованием стековых. Третий - с помощью так вами любимых графов, когда происходит парсинг целевой функции с целью определения процедурных ветвлений. Управление на выходе можно получить используя как прямую замену адреса возврата, так и инвалидации оного. Короче, что-то я не догоняю, кто тут овощ, кто нет...
7mm Вы овощ тут. SomeFunction не известна, откуда вам знать кто сервис или функу какую вызвал. Решения адекватного я не видел, которое можно реально заюзать.
SomeFunction может и не быть, не суть важно. Или мы друг-друга не понимаем, или все мы немного овощи. Для вас ещё раз: из X может быть выделена сигнатура, чтобы её можно было проверить? Если да, то проверяете в цикле по всем стековым фреймам наличие этой сигнатуры. Если нет... Не знаю, может способ с графами и не достаточно универсален, ибо товарищ green указал на возможные сложности, да вы и сами знаете о них. Тогда, может быть стоит попробовать такую штуку: Вы в колбеке Y трейсите функцию X, с целью выполнения инструкции call. После этого, производите поиск наличия адреса занесённого в стек в последовательности стековых фреймов, лежащих выше фрейма Y. Если есть такой адрес, то значит, что вы попали в Y из X именно с этого call'а. Если нет, отпускаете поток и ждёте следующего процедурного ветвления.
7mm Мне лень читать всю вашу ахинею, вот http://www.wasm.ru/forum/viewtopic.php?pid=400383#p400383 простейшие задачи три, решение есть ? А матчасть всю вашу эту я знаю досконально, я спросил кто может решить проблему. Сказано что решить без исключений, какие есчо трассировки.