Нужно изменить исполняемый файл, в котором регистр обнуляется так xchg esi,eax, которая занимает 1 байт, есть ли ещё способы обнуления в 1 байт, или можно как то засунуть xor esi, esi (2 байта) в файл, не испортив его?
Можно засунуть, ИМХО. Всегда (ну почти), рядом с командой которую нужно изменить, есть не особо нужные команды (если программа на ЯВУ написана), которыми можно пожертвовать. Я так вот выходил из подобных ситуаций...
Нет, в том то и дело, что ненужных инструкций нету! Программа весит 800 байт! нужно как то подругому выйти из ситуации!
в нужном месте(так где необходимо что-то изменить) ставим jmp на_свободное_место на этом "свободном месте" пишем сначала те команды которые затер наш jmp потом необходимый код, потом возвращаемся еще одним jmp'ом к исходному месту, точнее к тому месту, с которого нужно продолжить выполнение программы если не понятно - читаем статьи по реверсингу
Если EAX неотрицательное, то обрати внимание на инструкцию CDQ (обнуляет EDX). А вообще, что за программа такая, если она 800 байт и притом 32-разрядная?
Взято с сайта Z0MBiE -------------------- 21 СПОСОБ ОБНУЛИТЬ РЕГИСТР ~~~~~~~~~~~~~~~~~~~~~~~~~~ Как-то ночью, от незаин делать был написан это текст. Здесь приводятся всякие способы обнуления регистров - от простых и до самых изощренных, но вот чего тут нет - так это полных извращений, типа обнуления по одному биту, автогенерируемого кода и т.п. 1. Обнуление MOV-ом mov r, 0 2. Заменяем MOV на эквивалентные ему PUSH и POP push <something-equal-to-0> pop r 3. Самый хакерский способ: вычитаем регистр сам из себя. sub r, r 4. Ксорим (тоже неплохой способ... но... как-то не то...) Попутно (c) на название картины: "арвихакер, ксорящий ворды в уме" xor r, r 5. Тоже неплохой способ, правда назаин никому не нужный. and r, 0 6. Более хитро: умножим на 0. imul r, 0 7. Сдвиг (не путать со спрыгом). X1+X2 в сумме больше/равно размера регистра в битах, по отдельности меньше. Меньше потому, что берется по модулю. shr/shl/sal r, X1 ; X1<=31, X2<=31, X1+X2>=32 shr/shl/sal r, X2 ; 8. Более извратный сдвиг. clc rcr/rcl, X1 clc rcr/rcl, X2 9. Не совсем честный способ, но... or reg, -1 inc/not reg 10. Обнулим (E)CX. (хотя так можно и озаинеть) loop $ 11. Обнулим EDX. shr eax,1 cdq 11. Обнулим AL. (AH=AL,AL=0) aam 1 12. Обнулим AH aad 0 13. Опять AL clc setalc ; opcode: 0xD6 14. Более хитро: прочитаем 0 из порта (например порт 81h) mov dx, <some-port-number> in al, dx 15. Опять AL stc setnc al 16. А тут кто-нибудь в доку полезет. 5 раз bsf либо bsr. bsf r, r bsf r, r bsf r, r bsf r, r bsf r, r 17. Воспользуемся нулевым дескриптором из GDT sgdt [esp-6] mov r, [esp-4] mov r, [r] 18. Считаем ноль из сегмента FS (PE файл) mov r, fs:[10h] ; константа по вкусу, был бы ноль 19. Цикл (повторюсь: здесь главное не озаинеть) inc/dec r ; это несколько долго jnz $-1 20. Вызовем какую-нить функцию с кривыми параметрами (вернется NULL в EAX) call GetCurrentObject 21. Используем сопроцессор fldz fistp dword ptr [esp-4] mov eax, [esp-4] 22, 23, 24, ... Предлагаются также следующие варианты обнуления регистра: - сканирование цепочки обработчкиков SEH до победного нуля - сканирование цепочки хендлов файлов до нуля (для этого надо сначала положить в регистр хендл открытого файла нулевого кольца, а перед этим перейти в ноль и открыть этот файл) - считывание нуля из случайного файла (потребуется генератор случайных чисел) - вычисление синуса от Pi * n (умножать командой FMUL) - сортировка памяти и поиск нуля как минимального элемента - определение нуля как константы (в исходнике) - создание специального макроса для генерации нуля
Asterix, с начала EP до конца файла пустых, ненужных мест нету, зато до EP есть куча 00, думал туда записать код, а программа вылетает, посмотрел в отладчике, а там адрес перехода вместо 00400*** поменялся на 00800*** ну и соответсвенно он пытается перейти туда, а там ничего нету. Можно ли записать код до EP, чтобы он исполнялся? или может я что то не так делаю? а ниструкции для обнуления регистра - среди нету ни одного однобайтового! Как ещё можно решить задачу?
Asterix 800 БАЙТ PE формат, обычный виндосовский exe'шник... переписать его не трудно, но после компиляции становится 1,29Кб(вместе с DosStub и удаленными ненужными секциями), а мне нужно как можно меньше
Один байт может принимать 256 различных значений. Выпишем все однобайтовые команды (двоичные КОПы): Код (Text): 000**11* PUSH/POP ES/CS/SS/DS 001**111 DAA/DAS/AAA/AAS 010***** PUSH/POP R16/32 0110000* POPA/PUSHA 011011*w INS/OUTS 10010*** XCHG R16/32,eAX 10011000 CBW/CWDE 10011001 CWD/CDQ 10011011 WAIT 1001110* PUSHF/POPF 1001111* SAHF/LAHF 101001*w MOVS/CMPS 1010101w STOS 101011*w LODS/SCAS 1100*011 RETN/RETF 11001001 LEAVE 110011** INT3/INT I8/INTO/IRET 11010111 XLAT 111011*w IN/OUT ACC,DX 11110000 LOCK 1111001* REPNZ/REPZ 1111010* HLT/CMC 111110** CLC/STC/CLI/STI 1111110* CLD/STD
rmf с этого и нужно было начинать, ты напиши тогда код, раз не сложно, и кинь сюда, может мы и меньше чем 800байт сделаем
rmf > "а мне нужно как можно меньше" И для чего же позвольте узнать ? На диске он у тебя все равно будет занимать 2 сектора, т.е. 1024 байта И вообще не понятно чего ты зациклился на однобайтовой инструкции, хотя кроме особых частных случаев xor,cdq и lodsd ничего "придумать" невозможно. Поясни задачу и выложи код - может найдется другое решение. Например, непонятно почему нельзя изменить инструкцию записи в данный регистр - ведь в него что-то должно записываться. Для чего нужно изменять регистр - это возвращаемое значение или что ? Если просто проверка условия, то можно просто jcc изменить на противоположный. Со свободным местом тоже не ясно - неужели нет никаких дырок\выравниваний нопами или CC ? Одним словом давай код и поясни в каком месте и зачем нужно обнулять регистр
Выложить код наверное нельзя, потомучто это что то типа трояна(bindshell). Программа открывает шелл на определенном порту, ловится касперским, нужно что то изменить в коде чтобы не ловился... банальное изменение инструкций обнуления, и касперский уже не ловит, весь остальной код вроде нельзя поменять! В WASM.VIROLOGY не писал, потомучто особо к тематике того топа и не относится!
staier, так я же написал что он уделан. Всё решилось перекомпилированием, и удалением с конца файла кучи нулей, получился нужный размер. (спасибо автору) Но вопрос остался, можно ли как то написать код в середину файла(вместо кучи 00h), ДО EP, а после EP сделать jmp на тот кусок, который после выполнения сделает ret или jmp обратно?
rmf Можно, если осторожно > адрес перехода вместо 00400*** поменялся на 00800***" Значит неверный операнд jmp. Абсолютного jmp с непосредственным операндом не существует. Есть относительный jmp delta, где delta = target-next (target - адрес инструкции на которую происходит переход, next - адрес инструкции, следующей за jmp). Или косвенный абсолютный переход: mov eax,target + jmp eax Разберись с PE-заголовком или посмотри адреса в отладчике и посчитай дельту (раз прыгаешь назад, то она д.б.отрицательной)
leo, можешь написать где об этом почитать? адреса в отладчике смотрел, менял прямо там, если в отладчике менять, то все работает!