Сейчас на форуме: _MBK_, user99, ManHunter (+8 невидимых)

 eXeL@B —› Основной форум —› Проблемы с работой Win32 API
Посл.ответ Сообщение

Ранг: 4.6 (гость)
Активность: 0.010
Статус: Участник

Создано: 18 ноября 2005 14:52
· Личное сообщение · #1

Доброе время суток, господа.
наткнулся на интересное явление при модификации чужого кода в памяти во время выполнения.
Дело такое: кус кода встраивается в процесс (WriteProcessMemory+CreateRemoteThread) и грузит в контекст жертвы заданную длл-перехватчик.....
После завершения "внедрежного" потока дллка в памяти процесса есть, и пытается работать.
В ней я перехватываю управление в 2х точках жертвы - ставлю переходы на свой код (оригинальные байты, ессно выполняю, но потом).
Жертва многопоточная, но на этапе срабатывания патча- самое начало работы - поток всего один.
Проблема такая - любой вызов АПИ (CreateFile,CreateDirectory,MessageBox,etc) завершается ошибкой, GetLastError() после "файловых" вызовов отдает 998 - Invalid access to memory location.
дллка написана на С, рантайма нети(точнее не должно быть). Ф-ции Virtual* работают прекрасно.....
Вопрос: что сие может быть и как лечить?
Спасибо.



Ранг: 64.6 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 ноября 2005 14:55
· Личное сообщение · #2

entusiast
Если тебя не затруднит, ВОЗЬМИ ДЕБАГЕР и ПОСМОТРИ куда передаётся управление с твоих jump-ов.



Ранг: 4.6 (гость)
Активность: 0.010
Статус: Участник

Создано: 18 ноября 2005 14:59
· Личное сообщение · #3

Вообче-то, это я уже проделал. Код системных либов там честный.....
и мой код тоже вызывается так как нужно. Все планируемые параметры оказываются на своих местах... адреса стековых и глобальных переменных тоже в порядке, как и их содержимое.

PS. и нечего орать Если б проблемы были на моей стороне кода - уж наверное, заметил бы....



Ранг: 64.6 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 ноября 2005 15:02
· Личное сообщение · #4

entusiast пишет:
нечего орать

Пострараюсь
Как ты избавляешься от джампов ? Или емулируешь первые инструкцию ?



Ранг: 4.6 (гость)
Активность: 0.010
Статус: Участник

Создано: 18 ноября 2005 15:11
· Личное сообщение · #5

эээээ. уточни, плз. кто сказал про джампы???? Что ты имеешь в виду?
Поскольку патч сильно специализирован под версию жертвы, то я просто жестко вшил оригинальный код.
ессно, нв место перехвата ставится jmp, там я забочусь о сохранении всех регистров, потом call Engine, потом восстановление регистров, потом оригинальный код - там по 2-3 команды типа push reg/ call reg+offs и джамп обратно....



Ранг: 64.6 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 ноября 2005 15:17 · Поправил: Step
· Личное сообщение · #6

Вообщето исходники, или фрагмент кода был бы не лишним.
Когда ты делаешь джамп обратно, стек валиден ? Проверь есть ли все аргументы на верхушке, eip возврата, и естественно перед всем этим должны в стеке лежать результаты проэмулированных команд (типа push ebp).


entusiast пишет:
в место перехвата ставится jmp, там я забочусь о сохранении всех регистров,

Ты это делаешь в перехваченной DLL ? Не в своей функции а именно в чужой API ?



Ранг: 4.6 (гость)
Активность: 0.010
Статус: Участник

Создано: 18 ноября 2005 15:41 · Поправил: entusiast
· Личное сообщение · #7

Step пишет:
Когда ты делаешь джамп обратно, стек валиден ?

а как же? Жертва-то продолжает работу..... и грузится даже
это враппер основной штуки:

void __declspec(naked) engine_wrap()
{_asm{
pushad// save regs
pushf// -- flags
push ebp //length
push edi //data_ptr
push ecx //blockname
call Interceptor
popf// restore eflags
popad // restore regs
////// original code
call [eax+14h]
push edi
mov esi,eax
/////// eoc
push victim_continue
retn
}}

а вот она сама -
[c]
void __stdcall Interceptor(const char* name,void* _ptr,DWORD blksize)
{
DWORD err=GetLastError();
char fn[MAX_PATH];strcpy(fn,name);
for(unsigned i=0;i<strlen(fn);i++)
if(fn[i]=='/')fn[i]='.';
HANDLE hFile=CreateFile(fn,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_NEW,FILE _ATTRIBUTE_NORMAL,NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
DWORD dwWr;
WriteFile(hFile,_ptr,blksize,&dwWr,NULL);
CloseHandle(hFile);
}
else
GetLastError();
SetLastError(err);
}
[c]
Все значения наблюдаю. оптимизация на всяк случай оторвана...

вот, забыл утонить. враппер сажается во вражью длл, штука - в моей.



Ранг: 64.6 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 ноября 2005 15:49
· Личное сообщение · #8

Ещё раз, какие АPI ты перехватываешь ?
В твоём коде я вижу вызовы WriteFile, CreateFile.
Ты не в мёртвый цикл попадаешь ? Если ты эты ф-и перехватываешь, то ...



Ранг: 62.9 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 ноября 2005 15:57
· Личное сообщение · #9

Юзай не pushf/popf, а pushfd/popfd и будет тебе щастье.



Ранг: 4.6 (гость)
Активность: 0.010
Статус: Участник

Создано: 18 ноября 2005 16:18
· Личное сообщение · #10

Step: Эти ф-ции я не трогаю. там откуда-то куда-то передается буфер на обработку. в этот момент я его цапаю и пытаюсь записать в файл.....
ASMax: пофиг...... проблема не в том, что жертва падает после выполнения моей ф-ции, а в том, что мой код обламывается
Кстати, может просто не хватает стека? Стек-то тут чужой получается...... а восстанавливается правильно.



Ранг: 64.6 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 ноября 2005 16:27
· Личное сообщение · #11

Знач так.
1) Поставь брейкпоинт в теле API ф-и, там где нет твоего кода (после engine_wrap).
2) Запиши на бумажку регистры.
3) пункт 1 и 2 только уже без перехвата.
4) Сравни результаты (регистры).



Ранг: 4.6 (гость)
Активность: 0.010
Статус: Участник

Создано: 18 ноября 2005 16:59 · Поправил: entusiast
· Личное сообщение · #12

Step: Спасибо за совет. Решил проблему так:

pushad
pushfd
cld // API don't like CF ......
// init stack
push ebp
push edi
push ecx// saved needed parameters
push PAGE_READWRITE
push MEM_COMMIT
push 0x100000
xor eax,eax
push eax
mov eax,VirtualAlloc
call eax //get buffer for stack
pop ecx
pop edi
pop ebp // virtAlloc destroyed some - now restore
mov ebx,eax
push ebx // save Buffer for further VirtualFree
add ebx,0x100000 /point to end of buffer - stackops decreases addresses
sub ebx,4 // reserve dword for old esp
mov [ebx],esp // save it...
mov esp,ebx // set new stack 1Mb seem to be enough
push ebp //length
push edi //ptr
push ecx //blockname
call Interceptor // stdcall f-n will clear params...
pop esp // restore original stack
pop esi // original buffer is unneeded now
push MEM_RELEASE
push 0
mov eax,VirtualFree
call eax // free it
popfd //restore context
popad
// destroyed original victim's code
call [eax+14h]
push edi
mov esi,eax
// now stack-jump back to victim
push Continue
retn


действительно, не хватало стека......


 eXeL@B —› Основной форум —› Проблемы с работой Win32 API
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати