Это копия, сохраненная 19 августа 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Вы пишите на ассемблере или собираетесь начать на нём писать? Программируете микроконтролёры, пишете драйвера для ОС, а то и саму ОС? Вам сюда.
Вы изучаете алгоритмы работы закрытого софта, пишите патчи бинарников? Вам тоже сюда.
Попрошайки с "решите лабу по асме за меня" идут в общий тред, а лучше нахуй.
Шапка треда в процессе пополнения, пока так.
Книги по RE:
https://beginners.re/ - "Reverse Engineering для начинающих"- бесплатная современная книга на русском языке. К прочтению вкатывающимся и прочим ньюфагам обязательна!
https://mega.nz/#!Bc9VVAYC!Vk6CFlW6VIoskLNgDKXbsL6FacDQeOKe6LX92wNicKY Нарваха практический курс по дебагингу
https://www.goodreads.com/shelf/show/reverse-engineering - список книг
Сайты по RE:
http://wiki.yobi.be/wiki/Reverse-Engineering
https://www.reddit.com/r/ReverseEngineering/comments/hg0fx/a_modest_proposal_absolutely_no_babies_involved/
http://www.program-transformation.org/Transform/ReengineeringWiki
http://blog.livedoor.jp/blackwingcat/
https://yurichev.com/blog/
http://wiki.xentax.com/index.php/DGTEFF
Инструменты для RE:
1) IDA Pro 7.0.torrent
2) IDA Pro 6.8.torrent
3) IDA Pro 5.0 - бесплатная версия для некоммерческого использования
4) Остальное
Все книги и статьи Криса Касперски (R.I.P.)
https://yadi.sk/d/CxzdM1wyea4WP
+ https://rutracker.org/forum/viewtopic.php?t=272818
Книги по ассемблеру:
"Архитектура компьютера" Э. Таненбаум
С.В. Зубков: Assembler. Язык неограниченных возможностей.
Сайты по ассемблеру:
Замена почившему wasm.ru- https://wasm.in/
https://www.unknowncheats.me/wiki/Assembly
http://asmworld.ru/
https://software.intel.com/en-us/articles/intel-sdm
http://www.nasm.us/doc/
https://sourceware.org/binutils/docs/as/index.html#Top
https://msdn.microsoft.com/en-us/library/afzk3475.aspx
Для ковыряющих винду и софт под неё, сайты с описанием структур со смещениями и разными версиями оных:
http://msdn.mirt.net/
http://terminus.rewolf.pl/terminus/
http://geoffchappell.com/
Предыдущие
№2 https://arhivach.org/thread/255168/
№3 https://arhivach.org/thread/301316/
Абу пидарас убери рекапчу
Почему при двух идентичных состояниях регистров (кроме ebp/esp) она в ecx пихает совершенно разные значения?
FS - сегментный регистр, ссылающийся на сегмент с ненулевой базой, в котором по FS:0 лежит структура TEB. В TEB по 0x18 лежит "нормальный" адрес TEB. А по 0x2c лежит адрес массива указателей TLS, индексируется TLS-индексом, назначенным системой для модуля или выделенным с помощью TlsAlloc() (динамический TLS). Если это статический TLS, тогда по указателю лежит область памяти, содержащая thread-local переменные модуля. В противном случае все зависит от реализации.
> она в ecx пихает совершенно разные значения?
Массив выделяется из кучи при создании процесса, соответственно и адрес плавает.
Предлагаешь воспользоваться имеющимися наработками? Или просто ознакомиться для большего понимания*
int main() {return 1234;}
под turbo c compiler (1987-88 г.)
скажите,почему в обджект файле все так просто (получил через obj2asm):
;_main:
pushBP
movBP,SP
;; movAX,04D2h
jmp shortL8 хотя sourcer пишет что это delay for I/O, но никаких I/O не происходит
;L8: popBP
ret
а экзешник раздувается под 5 кб? Там куча запросов версий доса и векторов прерываний, хотя это, имхо, нафиг не надо. Или я не прав? Так как с этим нереально работать в отладчике, то надо уходить от этого палеолита?
Interrupt 1Ah : Real time clock ah=func xxh
Interrupt 1Ah : ah=00h get system timer count cx,dx
Interrupt 21h : DOS Services ah=function xxh
Interrupt 21h : ah=25h set intrpt vector al to ds:dx
Interrupt 21h : ah=30h get DOS version number ax
Interrupt 21h : ah=35h get intrpt vector al in es:bx
Interrupt 21h : ah=40h write file bx=file handle
Interrupt 21h : ah=4Ah changememory allocation
Interrupt 21h : ah=4Ch terminate with al=return code
push BP
mov BP,SP
mov AX,07CEh
jmp short L8
;L8: pop BP
ret
И вообще, насколько необходим этот инструмент?
спасибо! Я так и знал, что Сусликов - пидор. Тот же Hex Editor Neo по возможностям, имхо, перекрывает хуёв. как только manhunter не ослеп пердолиться в консольку? Но в последнем можно патчить в мнемониках асма..
Вообще, нужен опыт, тот же CyberGod на кряклабе круто запатчил Personal Editor 64: всего два байта.., но как он их нашёл? Какой логикой? Байты отстоят далеко от сообщений о регистрации, вложенность большая, нет однозначного джампа - есть sete и последующая проверка регистра х/з где..
п.с. может, конечно, нашёл старую версию и патч к ней и посмотрел примерные места патча..
> Неофит ITT. Зачем в программе раскиданы CC? Антиотладочный прием?
Просто заполнение пустых мест между функциями (как видишь адреса функций выровнены). Перекресных ссылок на них нет, так что заменить можешь на что угодно и ничего не поменяется. Ну а CC используется исторически чтобы случайно не выполнить непойми что когда хакер Васян тебе переполнение стэка устроит.
Дополню: смысл не столько в этом. Смысл еще и в том, чтобы остановить спекулятивную предвыборку инструкций, потому что чаще всего инструкции следующей функции никому нахуй не вперлись.
Памахити с ida pro 7.0.
Или ее криво взломали, или она сама кривая... В общем, если сделать синхронизацию сначала основного листа с псевдо-кодом, а затем с Hex'ом, то Ida закрывается с ошибкой на картинке.
Самостоятельно не фиксится, может, есть какой-то способ?
Я знаю, что можно переключаться по табу, и даже привык к этому, но если есть что-то, то дайте мне знать об этом.
И еще, в 6.8 версии было намного удобнее с Hex-листом, так как нужное значение строки при наведении в asm-листе постоянно переносилось влево, но тут hex статичен. Че делать, как исправить?
> И что значит 270000 (FFF)?
База (старт) и лимит.
> Но из этого описания я не понял как, например, перейти в hex dump'е в этот регистр?
Перейти в сегмент, ты хотел сказать? Да, можешь просто ввести адрес. А можешь Ctrl+G в окне дампа и сказать [fs:0x18] (по офсету 18 в fs хранится адрес, тот же самый, что ты видишь в окне регистров).
Спасибо, Кэп!
подскажи лучше, как сделать более "понятной" Иду? Чтобы как в х64/odbg показывались значения переменных, дампа, регистров, стека. Чтобы строки автоматом писались в виде комментариев в листинг, чтобы условные бряки ставить на стек и регистры, чтобы поиск строк был более хороший (а не как сейчас, пока не укажешь - не ищёт)
бац:
__try{
__asm int 0x3
}
__catch()
{
bool debuggerDetected=false;
}
?
Если да, то как это перехитрить и распознать в асм-листинге и если я не прав то что это вообще такое?
huipizda:
inc eax // делаем какую-нибудь хуйню
jmp ebx // прыгаем обратно. это обязанность коллера проставить правильный ebx
Ну это древний скучный трюк, им даже ольгу первую не задурить вроде. Суть простая - дебаггер использует int3 (0xcc) для брейкпоинтов. Брейкпоинт вызывает исключение, исключение передается дебаггеру. Если дебаггер тупой, то не сымитирует для отлаживаемой программы исключение, а просто проглотит его и продолжит. Если программа не отлаживается, или отладчик нормальный, исключение никто не проглотит, управление получит обработчик исключения в программе и выставит флаг.
> jmp ebx // прыгаем обратно. это обязанность коллера проставить правильный ebx
Твоя функция вызывается более чем из одного места. Куда прыгать будешь, куда мать посадишь?
Никаких, когда у тебя MIPS, ARM, OpenRISC или RISC-V.
А когда у тебя x64, M68k или SPARC — жри сладкий хлебушек и не проси больше.
У меня лейблы - это, считай, номера строк. Перед джампом в регистр пишеться, куда "функции" потом джампать:
mov ebx some_label
jmp huipizda
И в хуйпизде:
jmp ebx
Все.
Динамеские лейблы, короче.
Да не, он у меня вообще будет интерпретироваться, игрушка считай.
И чем это отличается от call?
Тебе нужена инструкция branch & link как в АРМах. Только если хуйпизда другие функции вызывает, придется как-то адреса возврата менеджить. На стек складывать или по фиксированным адресам, если reentrancy не нужно.
Мне один пиндос с OC рассказал что можно якобы безопасно хукать d3d9.Direct3DCreateEx ибо этим занимается не только малварь, а еще и фрапс, для захвата видео, к примеру.
Насколько это правда?
кури Proxy Dll или Dll Hijacking - можно что угодно хукать, не вмешиваясь в код процесса
Собственно вопрос: а в сегментах данных исполняться нельзя что ли? А в сегменты исполняемого кода в таком случае писать вообще можно? Как же тогда делать атаку через переполнение буфера, если нет сегментов, которые одновременно и для записи и для исполнения? Я пришёл к такому выводу, потому что через GDB у меня всё работает как я задумал, а без него программка сегфолтится.
Не хочу, чтобы вы мне рассказывали как проходить уровень, но хотелось бы, чтобы кто-нибудь ответил на мой вопрос про сегменты и пояснили про них поподробнее, если мои подозрения верны.
По-хорошему, исполняться из .data нельзя, потому что NX-бит, а можно ли писать в .text - зависит от линкера (чаще нет). Атаку на переполнение буфера можно делать через ROP.
>>137177
Теоретически ODA есть, но она говно. Зачем тебе на JS? Как вообще тебе в голову JS приходит, когда ты думаешь о байтоебле?
>Как вообще тебе в голову JS приходит, когда ты думаешь о байтоебле?
Байтоёб уровня /b/ пишет на JQuery на жабаскрипте. Ну хотя бы от нуля считает.
В /vn/ не пробовал обратится? Тут сидят суровые дядьки, ковыряющие Asm, а не скрипты интерпретаторов.
>Теоретически ODA есть, но она говно. Зачем тебе на JS? Как вообще тебе в голову JS приходит, когда ты думаешь о байтоебле?
Да всякие редиректы и части js эксплоитов.
спасибо, там какой-то тред про реверс визуалок и в правду есть
Ааа, тебе flow именно JS-кода? Нет, таких не знаю. Напиши, лол.
Проиграл.
> Атаку на переполнение буфера можно делать через ROP.
Спасибо большое за подсказку про NX бит и про ROP! Почитаю про это.
имхо, за этим будущее, среди аутистов, прогающих фо фан:
http://www.easycode.cat/English/index.htm
ставишь fasm, настраиваешь пути, редактор ресурсов, удаляешь прочие компили. Собирает одной кнопкой под х86/х64, полные либы и инклуды, большое сообщество (фасма). В visualmasm понравился файл помощи по API в hlp, хотя, для профессионалов надо качать новый сдк.
Смотря кому.
Собственно, чем отличается создание реализаций сетевых протоколов на асме от создании на нём каких-либо других приложений?
Как я понимаю, сетевым интерфейсам, по-сути как и любым другим устройствам, выделяется некая область памяти, которая играет роль буфера I/O. Процессор считывает из этой области данные и, в соответствии с инструкциями сетевого протокола, их обрабатывает. Есть ли какие-либо мануалы/статьи, в которых описывается работа сетевых интерфейсов на самом низком уровне (не считая, собственно, непосредственное преобразование данных в электромагнитные волны на линии передачи данных)?
> Собственно, чем отличается создание реализаций сетевых протоколов на асме
Тем, что ты заебешься реализовывать сетевые протоколы на асме. Как и другие приложения. Возьми си и не выебывайся.
> выделяется некая область памяти
Не совсем. В общем случае девайс знает, что некоторый регион адресного пространства - его собственный (иногда это захардкожено, иногда девайс можно ремапить, изменяя этот регион). Девайс висит на некоторой системной шине и перехватывает запросы к своим адресам, таким образом чтение идет из его собственной внутренней памяти. Например по 0-0x20000000 у тебя DRAM, а по 0x60000000-0x60001000 - Ethernet MAC. А уж что у него там внутри - многокилобайтный FIFO или всего лишь десяток 32-битных регистров - зависит от реализации. Где-то DMA есть, который будет вместо тебя процессора копировать данные из оперативки, а где-то единственное, что доступно - это постоянная долбежка регистра своими байтиками, а где-то вообще TCP в железе реализован, включая автоматические ретрансмиты.
> Есть ли какие-либо мануалы/статьи
Есть. Берешь даташит на железку, и там будет описано, как инициализировать, куда срать и как получать данные. Нет даташита? Ты в жопе. Даже при наличии существующих прошивок разобраться, как конкретно работать с железкой - очень сложная и времязатратная затея.
Это когда ты переходишь по ссылочке, а там есть ссылочка, чтобы вернутся обратно.
по реверсу без хорошего опыта работу найти анрил, ток в антивирусные лабы , паттерны для антивирей клепать
>хочу пойти по стопам бати
Твой батя вкатывался лет 15-20 назад, наверное. Сейчас в системное программирование почти никого не берут, там одни деды остались. Хотя если батя сможет устроить куда-нибудь, то почему бы и нет, главное, чтобы вышка была профильная.
Ты хоть для самого себя ответь нужен ли тебе асм? Писать код на ассемблере без желания мазохизм в чистом виде.
ADC BYTE PTR [EAX + ECX], BYTE PTR [EBX + ECX]
или
ADD BYTE PTR [EAX + ECX], BYTE PTR [EBX + ECX]
не компилируется? Я так понял, первый операнд у AD? - обязательно регистр, но чому так? Или просто так исторически сложилось и 2 области памяти никак не сложить?
> посоветуйте где почитать про устройство файловых систем
В википедии. Там ссылка на спеку MS по FAT есть.
>>141616
> Я так понял, первый операнд у AD? - обязательно регистр
Нет. В инструкции может быть только один memory operand. Первый он или второй - дело твое.
> просто так исторически сложилось
Не совсем. Причины даже не исторические,а архитектурные - там и способ кодирования инструкций не позволяет второй адрес закодировать, и длина инструкций увеличивается без особых выгод, и конвейер усложняется.
> 2 области памяти никак не сложить
Нет. Загрузи один из операндов в регистр.
>Не совсем. Причины даже не исторические,а архитектурные - там и способ кодирования инструкций не позволяет второй адрес закодировать, и длина инструкций увеличивается без особых выгод, и конвейер усложняется.
Понял, об этом не подумал.
>Нет. Загрузи один из операндов в регистр.
Не, я понимаю, что можно байт скинуть в DL и его прибавлять к области памяти, просто думал может я чего то не знаю и есть однокомандное решение
0xf2 - префикс REP. Наличие REP RET втыкатеся в целях оптимизации, потому что в амуде кривой бранч-предиктор. Отключи в настройках ольки superfluous prefixes в одной из вкладок Analysis.
Эта опция уже была выключена. Что еще интереснее, я создал новый проект с теми же исходниками, и один раз он сработал, а потом снова нет
> амуде кривой бранч-предиктор
да-да, там в доке даже интеловском так написано по оптимизации. а какого вы лвл`а, коллега?
Просто надо было включить, а не выключить.
моя ошибка)) но сехи же можно выпилить, да и в целом заточить под минимальный размер
у вас руки не от туда растут(( вот тут проскрольте до dynamicbase и чекните как настраивать компил
>dynamicbase
и как релоки создают проблему для олли? разве они восстанавливаются после входа в OEP? и в коде у меня никакой анальной привязки к дефолтному 0x400000 нет.
вы блять не на oep, а на crt прологе, для начала обучения она нихуя не нужна
просто выпилите ее и отлаживайте что попроще
> И самое главное - это не объясняет, почему раз в 3-4 пересборки приложение ведет себя адекватно
Инкрементальная линковка. Какие-нибудь profile-based оптимизации? И я все равно не вижу проблемы в префиксах. Оно должно работать. Если не работает, скинь проблемый exe, я завтра гляну.
он просто не понимает, что это за код
> Какие то обработчики исключений, какие то DB F2, что это всё значит? В исходниках всего этого нет
Разве crt-пролог выполняется до передачи управления на OEP?
>просто выпилите ее и отлаживайте что попроще
>>141785
>>141786
Это всё здорово, но объясните пж почему раз в N попыток программа нормально дебажится в олли, и всегда дебажится через дебаггер в вижаке и работает, если запустить как отдельный процесс? Как на это влияет c runtime, и что это за херня с исключениями в начале, для чего она генерируется?
Ну вот щито это? Это ли вообще гасит олли? Дело ли в олли, или в чем то другом?
> Разве crt-пролог выполняется до передачи управления на OEP?
в данном контексте пролог был принят за мусор, а так на oep и находится
> исключениями в начале, для чего она генерируется?
советую почитать нарваху/каран
> что это за херня с исключениями в начале
Так у тебя исключения от CRT лезут? Это нормально. Добавь в список игнорируемых и нажми Ctrl+F9.
Все молодешь ГеЙПиДОрыЪ
всё, вроде догодался.
сходи на собеседование с ними, поболтай, задания посомтри какие. поймешь что да как, да они подскажут что подтянуть. На хабре полистай блок касперского антивируса, там всякие крекми есть интересные.
>Брать некого, т.к вся молодежь ушла в веб
так мейнстрим же. вкатываться легче.
А с реверсом/и глубоким пониманием что и как - надо быть упорнее, времени много тратить, опыт как то набирать. А с этим сейчас сложнее. Это раньше когда был диффицит информации, как то что есть, то и хавал, и все соки выжимал, и эксперементировал чтоб понять что и как. А сейчас информации море, тонешь в ней, порой дольше гуглишь решение, чем сделать несколько попыток самому победить. :(
Сам несколько раз пытался в это вкатиться, но работу работать надо, и еще много чего. Еще в универе надо было вкатываться :(
Интересно-интересно, но времени нет совсем :(
у них там хуевый блог)) вот у eset куда лучше
>сходи на собеседование с ними, поболтай, задания посомтри какие. поймешь что да как, да они подскажут что подтянуть
спасибо за совет, приму))
Насколько нудно клепать патерны?Из этого вообще развитие есть?
https://pastebin.com/LA6HBKYH
Ты и сюда пришел? Объясни, чего ты хочешь добиться. Зачем тебе инлайн-асм, зачем тебе lea?
void foo(int anything) { uinptr_t stack_copy[20]; memcpy(stack_copy, &anything, sizeof(stack_copy)); }
И все. Если нужен адрес вовзрата, то копируешь не с anything, а с ((uintptr_t *) &anything) - 1.
Инструкция call пушит значение регистра процессора eip на стек, как мне в функции вытащить этот адрес?
Алсо, если все делать правильно (для поддержки чего-то большего, чем x86), то в гцц внезапно есть __builtin_return_address(0), в других компиляторах тоже есть аналоги. Инлайн-асм зло.
Круто, а я и не знал про это, спасибо.
имеешь в виду понять, что за инструкция по адресу? только дизассемблировать
> Имеет место быть ASLR?
Ну так сделай printf("%p", main); в обоих случаях, и узнаешь сам. Другие указатели (буфер, например) тоже посмотри.
Ньюфаг все еще на связи. Судя по пикрилу имеет место быть таки ASLR, но вот особенность: последний байт адреса все время равен de. То, что первые три байта равны x00\x00\x55 еще ладно, но почему последний то все время один и тот же. Это происки gcc?
Не de, а 6de. И это перестает быть удивительным, если вспомнмить, что размер страницы - 0x1000 (4096) байт, т.е., 12 младших бит адреса задают смещение внутри страницы. Загрузчик, вне зависимости от того, рандомизируется ли адрес загрузки или нет, оперирует именно страницами - загружает файл в начало страницы, секции выравнивает на страницы, ядро права ставит страницам и т. д., поэтому ничего удивительного в этом нет.
Я так понял, ты о пикриле говоришь. Но возникло несколько вопросов:
1) В отладчиках отображаются линейные адреса?
2) Если используются линейные адреса, тогда что подразумевается под словом "отображение"?
3) Насколько велика разница между понятиями виртуальная и линейная память?
>Насколько велика разница между понятиями виртуальная и линейная память?
Линейная память (она же "плоская модель") - это когда не используются селекторы сегментов и вся память имеет непрерывное адресное пространство. В 64-битном режиме это единственная модель (в 32 битном режиме тоже можно использовать переключаемые через cs gs fs сегменты, но там они работают по другому - как указатели на таблицу дескрипторов). С сегментами и таблицей дескрипторов как раз связан один из костылей штеуд архитектуры, что страничная адресация работает поверх сегментного механизма и нам все равно нужно выделить минимум 1 сегмент размером со всю доступную оперативу.
Реальная память есть только в досе с ограничением в 1 мегабайт. Все что современнее 95 винды использует виртуальную память. И ядро операционной системы тоже виртуальную память использует, все отличие лишь во флагах привелегий на страницах и в том что операционная система имеет возможность в том числе и сама себе страницы выделять. Для 64-битного режима полная процедура выглядит так:
https://wiki.osdev.org/Entering_Long_Mode_Directly
> Я так понял, ты о пикриле говоришь
Ну да. Во всех современных ОС используется страничная адресация, поэтому чтобы выделить память, ОС рано или поздно приходится найти свободную страницу физической памяти и отобразить ее в адресное пространство процесса.
> Если используются линейные адреса, тогда что подразумевается под словом "отображение
Настройка таблицы страниц таким образом, чтобы при доступе к нужному тебе байту линейного адресного пространства он читался из нужной тебе страницы физической памяти. Проще говоря, маппинг - это когда у тебя есть какие-то данные, тебе похуй на их реальное расположение, но ты хочешь, чтобы программа нашла их по такому-то адресу. Или даже по нескольким разным, так тоже можно.
> Насколько велика разница между понятиями виртуальная и линейная память?
Линейные и виртуальные адреса можешь считать синонимами. Термин "линейная память" вообще не существует, есть линейное адресное пространство и адресация.
Знает кто где скачать полный курс данных видосов по at&t Ассемблеру в Линуксе? На канале CSC их почемуто ненашел, нашел только отдельные копии на других каналах
Версия ОС? Раньше GINA была, в которой можно было все, теперь winlogon credential providers, в которых почти нихуя нельзя (документация у MS на сайте). Да, можно патчить винлогон, логонуи и прочих.
Начнем с win10, опционально win 7 → win 10
>теперь winlogon credential providers
Чёрт. В этой ОС есть места, которые не портят при обновлении?
ОП
Хуясе, человек в проприентарном софте делает какие-то хотпатчи и жалуется на то что их ломает очередное обновление.
Я ревершу до состояния исходников, которые обратно компилируются в идентичный код, а не патчу существующие.
А жалуюсь я на урезание возможностей настройки. Когда читал "Внутреннее устройство Microsoft Windows", мне очень понравилась продуманность идеи с GINA, можно было написать своего провайдера авторизации хоть по измерению длины члена с фото с вебки, а сейчас узнаю, что всё опять порезали. И так везде, возможность настройки постоянно урезают, кнопки прибивают гвоздями. Проводник в сраной XP можно было изменить до неузнаваемости, любую панельку или менюшку можно было перетащить или вовсе отключить. А сейчас всё прибито гвоздями, и люди радуются каким-то сраным 3,5 настраиваемым нанокнопочкам в заголовке. Тьфу, что я тут распинаюсь.
Сможет ли пользовательский процесс получить десктоп в нулевой сессии? Если я получу хэндлер десктопа, то в него можно запихнуть окно? Как мне получить десктопы, порожденные explorer'ом? Вообще, судя по пикрилейтед десктопы над процессами в иерархии, получается процесс может создать десктоп, но владеть им не будет, максимум иметь хэндл на него?
>Сможет ли пользовательский процесс получить десктоп в нулевой сессии?
Нет, она онально огорожена от кулхацкеров.
Чому у тебя на первом скриншоте отладка виндового приложения? Тебе нужно делать Attach->Remote GDB debugger.
На том скриншоте не туда нажал, но суть не меняется: при таком подключении выдает "bogus or irresponsive server". Я пытаюсь подключиться через Debugger -> Run -> Remote Linux Debugger.
Если пытаюсь использовать Debugger -> Attach -> Remote Linux Debugger, то выдает то же самое.
Суть не меняется. Тебе слишком рано что-то делать в IDA. Для начала тебе нужно научиться читать: Remote GDB debugger. То, что ты выбираешь - это когда ты собственный линуксовый стаб от IDA (из IDA/dbgserv/ копируешь в Linux и работаешь через него.
Я сразу пункт с GDB и не заметил, но мне от этого ничуть не лучше: я забыл что elf у меня 64-битный, а ида нет. Полную версию иды без вшитых васянами вирусами не найдешь. А ценник конский.
Седьмая ида совершенно 64-битная, совершенно легально и фриварно лежит на официальном сайте. С возможностями там не очень, ограничения мешают жить, но x86 есть. Посмотри, может оно в отладку тоже умеет.
>Полную версию иды без вшитых васянами вирусами не найдешь.
Прямо на рутрекере, антивири ругаются только на файл патчера ИДЫ, чтобы она открывала старые базы, созданные в пиратских версиях, можешь этот файл просто не качать, если больше доверяешь продажным анивирусам, чем мочераторам и пользователем рутрекера. Я скачал, брат жив, микроволновка греет еду.
Но мне же нужно положить DL в нижнее слово, находящееся по адресу BX. Или это что, мне надо сделать какой нибудь
AND DX, 00FFh
MOV [BX], DX
?
Да. Или movzx dx,dl (на байт короче).
> изменить какой-нибудь пиксель на монике
invoke GetDC,0
mov esi,eax
invoke SetPixel,esi,1,1,0ffff00ffh
invoke ReleaseDC,0,esi
> выдать какой нибудь писк на аудио выход
invoke MessageBeep,-1
Для остального идешь на MSDN и читаешь документацию по интресующей теме.
Ну и залез в функцию pgm_read_word() которая возвращает 16-битную переменную по адресу в программе и что же я вижу:
#define __LPM_word_enhanced__(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint16_t __result; \
__asm__ \
( \
"lpm %A0, Z+" "\n\t" \
"lpm %B0, Z" "\n\t" \
: "=r" (__result), "=z" (__addr16) \
: "1" (__addr16) \
); \
__result; \
}))
Описание для lpm здесь: http://www.microchip.com/webdoc/avrassembler/avrassembler.wb_LPM.html
Вкрации: lpm читает один байт по адресу, а мы получается читаем байты по адресу 160 и 176, как я понял.
То есть одно 16-битное слово занимает 32 бита в програмном пространстве?
Если да, то почему это так сделано?
> То есть одно 16-битное слово занимает 32 бита в програмном пространстве?
Попробуй яснее выражать свои мысли.
Нет. 16-битное слово занимает 16 бит. Но адресация для LPM байтовая, т.е., ты кормишь ему адрес байта (адрес слова * 2 байта в слове) в отличие от других инструкций, где ты кормишь адрес слова. LPM по-прежнему читает слово, но возвращает только один из байтов. Какой именно - зависит от младшего бита.
> а мы получается читаем байты по адресу 160 и 176
Чо?
Ну вот эта часть кода:
"lpm %A0, Z+" "\n\t" \
"lpm %B0, Z" "\n\t" \
Что именно делают эти инструкции? Они разве не из соседних слов читает? Для двойного слова инструкция выглядит так:
#define __LPM_dword_enhanced__(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint32_t __result; \
__asm__ \
( \
"lpm %A0, Z+" "\n\t" \
"lpm %B0, Z+" "\n\t" \
"lpm %C0, Z+" "\n\t" \
"lpm %D0, Z" "\n\t" \
: "=r" (__result), "=z" (__addr16) \
: "1" (__addr16) \
); \
__result; \
}))
> lpm %A0, Z+
Прочитали в младший байт result младшие 8 бит 16-битного слова, инкрементировали Z. В Z при этом установился младший бит, т.е., следующий lpm прочитает старший байт.
> lpm %B0, Z+
Прочитали во второй байт кусок result старшие 8 бит 16-битного слова, инкрементировали Z, при этом младший бит сбросился (1 + 1 (mod 2) = 0), тем самым мы перешли к чтению младших 8 бит следующего 16-битного слова.
> lpm %C0, Z+
Прочитали младшие 8 бит второго 16-битного слова, инкрементировали Z (младший бит установился), чтобы в дальнейшем прочитать старшие 8 бит.
> lpm %D0, Z
Прочитали старшие 8 бит второго 16-битного слова. Z инкрементировать не стали, т.к., больше ничего читать не собираемся.
Куда ты лезешь, если такого не знаешь? Инструкции в __asm - это текст. Чтобы инструкции были на разных строках, воткнули символ новой строки (\n), чтобы в листинге все было красиво выровнено, воткнули символ табуляции (\t). Если не втыкать эти символы, будет __asm("lpm %A0, Z+lmp %B0,Z+ итд.".
>Куда ты лезешь, если такого не знаешь?
Ну я же говорю, так на С писал, сейчас решил библиотеки раскопать, а там ассемблер оказывается.
Так это и есть стандатный сишный синтаксис строковых литералов.
Из пиков видно, что массив чаров объявлен раньше интов, а адрес у него больше. Это доказывает, что стэк растёт от большого адреса к маленькому. Но зачем так? И что в тех 12ти байтах после конца массива интов (804) и перед началом массива чаров (810)?
Как происходит малок? Это же операционная система должна найти место в памяти подходящего размера и записать в таблицу кем эта память занята. Так же и с виртуальной памятью. Или это всё на уровне хардвара в процессоре реализовано? Или как например происходят другие системные вызовы типа гетчар? Вот это процессор точно не может сам сделать. Значит процессор как-то отличает мою программу от программы операционной системы и помогает им общаться? Но как?
> что массив чаров объявлен раньше интов, а адрес у него больше. Это доказывает
Ровно нихуя не доказывает. Другой компилятор мог положить локальные переменные в другом порядке. Чтобы узнать, куда растет стек, нужно хотя бы раскидать локальные переменные по разным функциям:
void bar(int arg) {
printf("bar.arg at %p\n", arg);
}
void foo(int arg) {
printf("foo.arg at %p\n", arg);
bar(0);
}
int main(void) { foo(0); }
> И что в тех 12ти байтах после конца массива интов (804) и перед началом массива чаров (810)?
Что угодно. Другие локальные переменные, временные переменные, созданные компилятором. Можешь сдампить память и узнать (или компилировать с -S и или -save-temps и узнать гораздо быстрее и точнее).
> Как происходит малок?
Как-нибудь. Почитай K&R, там было чуть ли не упражнение по написанию своего маллока.
> Это же операционная система должна найти место в памяти подходящего размера
Менеджер кучи просит у ОС большой кусок памяти и поддерживает какую-нибудь свою структурку (например, linked list), в которой хранит список свободных и занятых блоков. Если в списке блоков нужного размера не находится, просит у ОС еще кусок памяти и т. д.
> Или как например происходят другие системные вызовы типа гетчар?
getchar() реализуется через read(), который реализуется через одноименный системный вызов. Дергается какое-нибудь программное прерывание или его аналог, процессор сохраняет контекст, переключается в привелигированный режим, код ОС дергает железку за порты, переключается обратно, восстанавливает контекст и продолжает выполнение. Ну это если MMU/MPU есть. Если нет, то просто дергаются функции ОС.
Можешь почитать классическую "Архитектуру компьютера" Таненбаума, там все гораздо более подробно.
> что массив чаров объявлен раньше интов, а адрес у него больше. Это доказывает
Ровно нихуя не доказывает. Другой компилятор мог положить локальные переменные в другом порядке. Чтобы узнать, куда растет стек, нужно хотя бы раскидать локальные переменные по разным функциям:
void bar(int arg) {
printf("bar.arg at %p\n", arg);
}
void foo(int arg) {
printf("foo.arg at %p\n", arg);
bar(0);
}
int main(void) { foo(0); }
> И что в тех 12ти байтах после конца массива интов (804) и перед началом массива чаров (810)?
Что угодно. Другие локальные переменные, временные переменные, созданные компилятором. Можешь сдампить память и узнать (или компилировать с -S и или -save-temps и узнать гораздо быстрее и точнее).
> Как происходит малок?
Как-нибудь. Почитай K&R, там было чуть ли не упражнение по написанию своего маллока.
> Это же операционная система должна найти место в памяти подходящего размера
Менеджер кучи просит у ОС большой кусок памяти и поддерживает какую-нибудь свою структурку (например, linked list), в которой хранит список свободных и занятых блоков. Если в списке блоков нужного размера не находится, просит у ОС еще кусок памяти и т. д.
> Или как например происходят другие системные вызовы типа гетчар?
getchar() реализуется через read(), который реализуется через одноименный системный вызов. Дергается какое-нибудь программное прерывание или его аналог, процессор сохраняет контекст, переключается в привелигированный режим, код ОС дергает железку за порты, переключается обратно, восстанавливает контекст и продолжает выполнение. Ну это если MMU/MPU есть. Если нет, то просто дергаются функции ОС.
Можешь почитать классическую "Архитектуру компьютера" Таненбаума, там все гораздо более подробно.
Бля, в коде в printf & забыл, ну ты понял.
-a 100
mov ax,6
mov bx,7
mul bx
mov bx,ax
mov cx,8
shl bl,1
mov al,0
adc al,30
int 29
loop 10d
int 20
Я нихуя не понял, что у тебя за код, и зачем там int 29. А как переводить:
1) Обнуляешь регистр с результатом.
2) Сдвигаешь регистр с результатом на 3 бита влео.
3) Берешь очередной символ восьмеричного числа, преобразуешь в двоичный вид (вычитаешь ASCII-код '0').
4) Объединяешь с результатом через add или or.
5) Повторяешь с шага 2.
Или тебе обратно нужно? Тогда берешь очередные три бита, прибавляешь '0', кладешь в буфер, повторяешь. При необходимости выводишь задом наперед.
А как код выглядит тогда?
Это graph view в иде. На чем написано - не имеет значение.
Да.
Инструкция:
mov edx,
mov dword ptr ds:[0x9DB2B8], 0
mov dword ptr ds:[0x9DB2B4], edx
mov edx, [a]
mov dword ptr ds:[0x9DB2BC], edx
mov dword ptr ds:[0x9DB2C0], edx
mov byte ptr ds:[0x9DB2C8], 1
Ты бы на русском для начала писать научился. ЯННП. В инструкции все так. В первой строке, очевидно, нужно второй операнд дописать. Префикс ds: можно выкинуть.
Какие секции в 32-битном защищенном режиме, поехавший? И вообще, ты с сегментами путаешь.
0. Не проебался ли я где то в рассуждениях выше? Ничего не пропустил и ничего не переусложнил?
1. Я поискал различные списки инструкций x86 и охуел от всяких расширений типа FPU, SIMD, MMX, SSE1/2/3/4. У них там какие то свои стеки, свои регистры, охуеть. Я как бы вообще не реверсер, но те несколько раз, что я расчехлял иду и олли, я никогда не видел всех этих st(0) FPOPA MMX и всего прочего. Из того, что я прочитал об
этих расширениях мне показалось, что это всё как бы виртуальная хуйня, которая всё равно в конечном счете преобразуется в голый классический x86 с его классическими ADD EAX EBX. Это так?
2. Можете посоветовать годных и максимально современных гайдов по написанию дизассемблера, где были бы приведены в коде структуры инструкции, процесс парсинга и всё такое? Всё, что я находил, там просто в общих чертах говорилось о структуре команды и всё такое, но никакой прям особой конкретики и подводных камней, которые мне кажется должны быть.
0. Не проебался ли я где то в рассуждениях выше? Ничего не пропустил и ничего не переусложнил?
1. Я поискал различные списки инструкций x86 и охуел от всяких расширений типа FPU, SIMD, MMX, SSE1/2/3/4. У них там какие то свои стеки, свои регистры, охуеть. Я как бы вообще не реверсер, но те несколько раз, что я расчехлял иду и олли, я никогда не видел всех этих st(0) FPOPA MMX и всего прочего. Из того, что я прочитал об
этих расширениях мне показалось, что это всё как бы виртуальная хуйня, которая всё равно в конечном счете преобразуется в голый классический x86 с его классическими ADD EAX EBX. Это так?
2. Можете посоветовать годных и максимально современных гайдов по написанию дизассемблера, где были бы приведены в коде структуры инструкции, процесс парсинга и всё такое? Всё, что я находил, там просто в общих чертах говорилось о структуре команды и всё такое, но никакой прям особой конкретики и подводных камней, которые мне кажется должны быть.
>. Это так?
Нет. Просто векторизация непростая штука, автоматически компиляторы оче редко ее могут сами применить, а интринсиками кодить то еще удовольствие. Их применяют в числодробильне и графике дабы выжать производительность, с повсеместным расппостранением gpu это почти потеряло актуальность,потому да, встретить можно редко и только в специфичном по. Декомпильни какой-нибудь opencv, скажем, там 100% есть sse.
>и если один из операндов - адрес, то к нему нужно прибавить дельту, которая образуется в результате моих действий.
И вот на этом моменте ты сосёшь, так как нельзя сходу определить, где константный адрес, а где смещение от текущего места. Даже я, сверх хуёвый реверсер, однажды наткнулся в IDA на место, где она проебалась, пришлось поправлять. А ведь иду пишут не первый год не самые тупые люди.
Если у файла есть таблица релокаций, то она тебе поможет потаскать код туда-сюда целиком секцией, но при добавлении внутрь всё равно возможен проёб, так как релоки учитывают возможность перенесения образа целиком, и не правят относительные адреса, а с ними возможен проёб выше.
>Насколько я понял, каждая инструкция имеет общую структуру, и я типа должен как то понять по первому байту что это за инструкция.
Если не применяются антиотладочные приёмы, то да.
>никогда не видел всех этих st(0) FPOPA MMX и всего прочего.
Просто повезло. Это математические расширения, применяются в игорях и работах с числами, в обычном коде разве что компилятор применит векторизацию, но редко когда.
>где были бы приведены в коде структуры инструкции, процесс парсинга и всё такое?
В шапке по ссылке https://software.intel.com/en-us/articles/intel-sdm гайды от интела, лучще него тебе никто не опишет. Но там тыщи страниц, ты охуеешь всё это читать.
АЛСО, я ОП-долбоёб, думаю скоро придёт сажа-кун и пояснит конкретно.
1) Автоматическое дизассемблирование произвольного кода невозможно. Ну то есть вообще, никак. Можно пытаться решать частные задачи: ограничиться каким-то набором компиляторов, закладываться на отсутствие кода, написанного вручную на ассемблере и/или сгенерированного протектором и т.д., но это нетривиально даже при условии использования какого-нибудь capstone, который разберет инструкции за тебя.
2) Зачем тебе добавлять импорт именно к существующему дескриптору? Все отлично работает, если добавить новый дескриптор (это нормально, существуют exe, собранные стоковыми тулсетами, в которых есть несколько дескрипторов для одной DLL).
3) Если тебе нужен не произвольный PE, а более-менее современный, то у них всех есть релоки, по релокам можно находить ссылки на IAT, что позволяет делать с IAT что угодно, с большой вероятностью ничего не сломав (если что-то ссылается на thunk, ты можешь это что-то поправить, не разбирая даже саму инструкцию).
> вставить свой код в уже существующий
Тут проще. Можно стащить из нужного места кода любое целое количество инструкций (понадобится дизассемблер длин как минимум), воткнуть jmp на свой код, а потом корректно выполнить оригинальный код и вернуться.
> где были бы приведены в коде структуры инструкции, процесс парсинга
Intel SDM уже посоветовали. Конкретно второй том, первые главы (instruction format) и Appendix A с бесконечными табличками инструкций. Как ты это парсить будешь - дело твое. Можно табличками и масочками, можно длинным свитчем и масочками. Это самая меньшая проблема.
Алсо, посмотри на готовые инструменты типа Intel PIN, DynamoRIO и т. д. Может, тебе и не нужно все это велосипедить? Но за динамическое инструментирование приходится платить производительностью - на некоторых алгоритмах ты вообще ничего не заметишь, но зато на других будешь сосать довольно сильно.
>>170331
Собираешь любой код с -m64, и вычисления с плавающей точкой будут на SSE, ибо FPU давно уже легаси. В 32-битном коде тоже можно (-mfpmath=sse), но из-за ABI оно не используется по умолчанию даже если сказать -msseX.
>>170337
Да мне добавить в общем-то нечего. Просто я сначала ответил, а потом увидел, что ты уже отписался.
1) Автоматическое дизассемблирование произвольного кода невозможно. Ну то есть вообще, никак. Можно пытаться решать частные задачи: ограничиться каким-то набором компиляторов, закладываться на отсутствие кода, написанного вручную на ассемблере и/или сгенерированного протектором и т.д., но это нетривиально даже при условии использования какого-нибудь capstone, который разберет инструкции за тебя.
2) Зачем тебе добавлять импорт именно к существующему дескриптору? Все отлично работает, если добавить новый дескриптор (это нормально, существуют exe, собранные стоковыми тулсетами, в которых есть несколько дескрипторов для одной DLL).
3) Если тебе нужен не произвольный PE, а более-менее современный, то у них всех есть релоки, по релокам можно находить ссылки на IAT, что позволяет делать с IAT что угодно, с большой вероятностью ничего не сломав (если что-то ссылается на thunk, ты можешь это что-то поправить, не разбирая даже саму инструкцию).
> вставить свой код в уже существующий
Тут проще. Можно стащить из нужного места кода любое целое количество инструкций (понадобится дизассемблер длин как минимум), воткнуть jmp на свой код, а потом корректно выполнить оригинальный код и вернуться.
> где были бы приведены в коде структуры инструкции, процесс парсинга
Intel SDM уже посоветовали. Конкретно второй том, первые главы (instruction format) и Appendix A с бесконечными табличками инструкций. Как ты это парсить будешь - дело твое. Можно табличками и масочками, можно длинным свитчем и масочками. Это самая меньшая проблема.
Алсо, посмотри на готовые инструменты типа Intel PIN, DynamoRIO и т. д. Может, тебе и не нужно все это велосипедить? Но за динамическое инструментирование приходится платить производительностью - на некоторых алгоритмах ты вообще ничего не заметишь, но зато на других будешь сосать довольно сильно.
>>170331
Собираешь любой код с -m64, и вычисления с плавающей точкой будут на SSE, ибо FPU давно уже легаси. В 32-битном коде тоже можно (-mfpmath=sse), но из-за ABI оно не используется по умолчанию даже если сказать -msseX.
>>170337
Да мне добавить в общем-то нечего. Просто я сначала ответил, а потом увидел, что ты уже отписался.
> ограничиться каким-то набором компиляторов
А это как влияет на сырые байты? Какая мне разница, кто транслировал код и с какого языка, если в итоге он всё равно биективно отображаем в ассемблерный листинг. Или я чего то не знаю о современных компиляторах? У меня ведь задача не восстановить точно было ли i = i+1 или i++.
>Зачем тебе добавлять импорт именно к существующему дескриптору?
Выглядит как то по уродски, по мне так это может служить знаком, что в файл могли что нибудь инжектить и докидывать недостающие импорты.
>Может, тебе и не нужно все это велосипедить?
Да, в идеале бы этого избежать. Сейчас смотрю на capstone, посмотрю еще на интел пин и динаморио. Мне бы в идеале какую нибудь C/C++ либу дизассемблирования с исходниками, чтобы я мог .lib себе собрать и из нее дергать нужный функционал.
>Тут проще. Можно стащить из нужного места кода любое целое количество инструкций (понадобится дизассемблер длин как минимум), воткнуть jmp на свой код, а потом корректно выполнить оригинальный код и вернуться.
Ну да, но при этом мне нужно либо пихать свой детур в хвост секции либо создавать новую, если в текущей места нет, но мне вот в идеале нужно инжектить где то внутри исполняемого кода, чтобы всё выглядело монолитно. И про дизассемблер длин почитал. Окей, а эту штуку как написать? Я так понимаю, мне так же придется считывать первые байты инструкций и по какой нибудь таблице определять длину? На вики/краклаб вики написано, что процессоры тоже определяют длину команды как то. Как такое вообще блять гуглить?
> Если тебе нужен не произвольный PE, а более-менее современный, то у них всех есть релоки, по релокам можно находить ссылки на IAT, что позволяет делать с IAT что угодно, с большой вероятностью ничего не сломав (если что-то ссылается на thunk, ты можешь это что-то поправить, не разбирая даже саму инструкцию).
Вот тут не понял к чему ты это. Пока пытался понять, задался следующим вопросом: Раз загрузчик может загрузить либу по любому адресу, все импорты обкладываются релокациями? А если я уберу dynamic base из nt optional header и обнулю data directory relocbase, и при этом в импорте будут либы с одним и тем же image base, то загрузчик жидко пёрднет и умрёт?. Ты предлагаешь вешать хук на вызов импортируемой функции? Типа по релокам и IAT я нахожу, что в таком то месте executable секции идет вызов импортируемой функции, и вот тут я меняю адрес call на свой хук, там делаю что мне надо, восстанавливаю стек и регистры и
вызываю импортируемую функцию, а затем ret?
> ограничиться каким-то набором компиляторов
А это как влияет на сырые байты? Какая мне разница, кто транслировал код и с какого языка, если в итоге он всё равно биективно отображаем в ассемблерный листинг. Или я чего то не знаю о современных компиляторах? У меня ведь задача не восстановить точно было ли i = i+1 или i++.
>Зачем тебе добавлять импорт именно к существующему дескриптору?
Выглядит как то по уродски, по мне так это может служить знаком, что в файл могли что нибудь инжектить и докидывать недостающие импорты.
>Может, тебе и не нужно все это велосипедить?
Да, в идеале бы этого избежать. Сейчас смотрю на capstone, посмотрю еще на интел пин и динаморио. Мне бы в идеале какую нибудь C/C++ либу дизассемблирования с исходниками, чтобы я мог .lib себе собрать и из нее дергать нужный функционал.
>Тут проще. Можно стащить из нужного места кода любое целое количество инструкций (понадобится дизассемблер длин как минимум), воткнуть jmp на свой код, а потом корректно выполнить оригинальный код и вернуться.
Ну да, но при этом мне нужно либо пихать свой детур в хвост секции либо создавать новую, если в текущей места нет, но мне вот в идеале нужно инжектить где то внутри исполняемого кода, чтобы всё выглядело монолитно. И про дизассемблер длин почитал. Окей, а эту штуку как написать? Я так понимаю, мне так же придется считывать первые байты инструкций и по какой нибудь таблице определять длину? На вики/краклаб вики написано, что процессоры тоже определяют длину команды как то. Как такое вообще блять гуглить?
> Если тебе нужен не произвольный PE, а более-менее современный, то у них всех есть релоки, по релокам можно находить ссылки на IAT, что позволяет делать с IAT что угодно, с большой вероятностью ничего не сломав (если что-то ссылается на thunk, ты можешь это что-то поправить, не разбирая даже саму инструкцию).
Вот тут не понял к чему ты это. Пока пытался понять, задался следующим вопросом: Раз загрузчик может загрузить либу по любому адресу, все импорты обкладываются релокациями? А если я уберу dynamic base из nt optional header и обнулю data directory relocbase, и при этом в импорте будут либы с одним и тем же image base, то загрузчик жидко пёрднет и умрёт?. Ты предлагаешь вешать хук на вызов импортируемой функции? Типа по релокам и IAT я нахожу, что в таком то месте executable секции идет вызов импортируемой функции, и вот тут я меняю адрес call на свой хук, там делаю что мне надо, восстанавливаю стек и регистры и
вызываю импортируемую функцию, а затем ret?
>вычисления с плавающей точкой будут на SSE
Нуок, но это всё-таки милипиздрическая часть SSE, по сути только арифметика и только плавающей точки, и та в формате "movsd - mulsd - movsd", т.е. несколько инструкций из сотни.
> Какая мне разница, кто транслировал код и с какого языка
Имея ограничания, ты можешь делать предположения. Что вот эту последовательность инструкций можно не разбирать, а брать как блок с известной функциональностью (всякие вещи, связанные с обработкой исключений или шаблонный код _initterm). Что какие-то вещи компилятор делать не будет (например, применительно к задаче про импорты, не станет делать position-independent code, или хотя бы не станет адресовать импорты таким способом). Что если данные ближе к началу RW секции - то для такого-то компилятора они на самом деле константа (например, таблица виртуальных функций).
> по мне так это может служить знаком, что в файл могли что нибудь инжектить и докидывать недостающие импорты
Я тебе поэтому и сказал, что это нормально так линковаться для нормальных приложений. Например, если это объектник и либа, и в одной символы с __imp__, а в другой без. Или если компиляторы объектника и либы разные.
> Окей, а эту штуку как написать?
Блять, формат инструкций в Intel SDM прочитай. Будет у тебя табличка опкодов с длинами, а ModR/M будешь разгребать по ходу дела. В 64-битном коде все чуть веселее из-за REX. Если сложно, то на васме было "Заклинание кода", оно гуглится, правда оно только для 32 бит. Алсо, есть упоротый и гарантированно работающий способ, для которого нужно строк 30 кода от силы гугли page fault isa analysis, но он неебически медленный и поэтому почти непригоден для практического применения.
> Пока пытался понять, задался следующим вопросом: Раз загрузчик может загрузить либу по любому адресу, все импорты обкладываются релокациями?
Да, потому что ты на импорты ссылаешься как на данные (грубо говоря, в 32-битном коде call [imported_func] или jmp [imported_func] читают дворд по абсолютному адресу, а значит на адрес дворда нужен релок).
> и при этом в импорте будут либы с одним и тем же image base, то загрузчик жидко пёрднет и умрёт?
Если у либ будут релоки, загрузчик выберет для либ незанятые адреса. А вот если адрес твоей либы будет уже занят на момент загрузки, и у тебя нет релоков, тебя пошлют нахуй.
> Ты предлагаешь вешать хук на вызов импортируемой функции?
Я предлагаю пройтись по релокам и посмотреть, не ведут ли адреса в IAT. Если ведут - запатчить новым адресом нужного элемента в IAT (если ты их, допустим, раздвинул, чтобы свое говно воткнуть). Это нормальный, стандартный подход, и для нормальных стандартных exe, сделанных нормальными компиляторами (см. выше), а не протекторами, он работает уже третье десятилетие. Но можно и подменять вызовы импортов на свои, как ты описал.
> C/C++ либу дизассемблирования с исходниками
Так capstone. И с исходниками, и поддержка любой архитектуры, которая может тебе присниться в страшном сне, и сборка лайт-версии только с нужной функциональностью.
Алсо, сдается мне, что ты малварку пилишь. Шел бы ты нахуй отсюда в таком случае.
> Какая мне разница, кто транслировал код и с какого языка
Имея ограничания, ты можешь делать предположения. Что вот эту последовательность инструкций можно не разбирать, а брать как блок с известной функциональностью (всякие вещи, связанные с обработкой исключений или шаблонный код _initterm). Что какие-то вещи компилятор делать не будет (например, применительно к задаче про импорты, не станет делать position-independent code, или хотя бы не станет адресовать импорты таким способом). Что если данные ближе к началу RW секции - то для такого-то компилятора они на самом деле константа (например, таблица виртуальных функций).
> по мне так это может служить знаком, что в файл могли что нибудь инжектить и докидывать недостающие импорты
Я тебе поэтому и сказал, что это нормально так линковаться для нормальных приложений. Например, если это объектник и либа, и в одной символы с __imp__, а в другой без. Или если компиляторы объектника и либы разные.
> Окей, а эту штуку как написать?
Блять, формат инструкций в Intel SDM прочитай. Будет у тебя табличка опкодов с длинами, а ModR/M будешь разгребать по ходу дела. В 64-битном коде все чуть веселее из-за REX. Если сложно, то на васме было "Заклинание кода", оно гуглится, правда оно только для 32 бит. Алсо, есть упоротый и гарантированно работающий способ, для которого нужно строк 30 кода от силы гугли page fault isa analysis, но он неебически медленный и поэтому почти непригоден для практического применения.
> Пока пытался понять, задался следующим вопросом: Раз загрузчик может загрузить либу по любому адресу, все импорты обкладываются релокациями?
Да, потому что ты на импорты ссылаешься как на данные (грубо говоря, в 32-битном коде call [imported_func] или jmp [imported_func] читают дворд по абсолютному адресу, а значит на адрес дворда нужен релок).
> и при этом в импорте будут либы с одним и тем же image base, то загрузчик жидко пёрднет и умрёт?
Если у либ будут релоки, загрузчик выберет для либ незанятые адреса. А вот если адрес твоей либы будет уже занят на момент загрузки, и у тебя нет релоков, тебя пошлют нахуй.
> Ты предлагаешь вешать хук на вызов импортируемой функции?
Я предлагаю пройтись по релокам и посмотреть, не ведут ли адреса в IAT. Если ведут - запатчить новым адресом нужного элемента в IAT (если ты их, допустим, раздвинул, чтобы свое говно воткнуть). Это нормальный, стандартный подход, и для нормальных стандартных exe, сделанных нормальными компиляторами (см. выше), а не протекторами, он работает уже третье десятилетие. Но можно и подменять вызовы импортов на свои, как ты описал.
> C/C++ либу дизассемблирования с исходниками
Так capstone. И с исходниками, и поддержка любой архитектуры, которая может тебе присниться в страшном сне, и сборка лайт-версии только с нужной функциональностью.
Алсо, сдается мне, что ты малварку пилишь. Шел бы ты нахуй отсюда в таком случае.
>понадобится дизассемблер длин как минимум
Взял как-то писать это для кастомного байткода, потому что меня интересовали только две инструкции из всего множества, в итоге написал всё целиком. времени потратил ахулиард.
Очень интересная информация.
>Алсо, сдается мне, что ты малварку пилишь. Шел бы ты нахуй отсюда в таком случае.
Нет, я пишу пытаюсь протектор в рамках курсовой/дипломной работы. Отсюда условия на инжектинг не в новую секцию или хвост какой нибудь, а размазать по всему коду. Отсюда же гарантии, что PE не будет упакован и обмазан другими протекторами.
> Отсюда условия на инжектинг не в новую секцию или хвост какой нибудь, а размазать по всему коду.
Побуду кэпом: защищать готовый исполняемый файл - скучно и бесполезно. Не думал взять LLVM IR и протектить его? Или хотя бы написать протектор-компоновщик для объектников? Можно попросить компилятор сделать -ffunction-sections/-Gy и тем самым значительно упростить себе жизнь.
))))
может кто пояснить за, как я понял, все аргументы в инструкциях могут иметь разный тип (регистров общего назначения нет), но я не очень догнал что там да как.
>Алсо, сдается мне, что ты малварку пилишь. Шел бы ты нахуй отсюда в таком случае.
Авер в треде? Ну будет тебе, милый
>Обычные пользователи, аверам наоборот выгодны вирусы.
Аверам вирусы сами не нужны, им нужен шум вокруг них. Сами семплы они ненавидят, ибо это адский поверсшел/вбс/джс. Типичному аверу никогда не доверят серьезный анализ, за них это делает, как правило, чел из другой конторы, который по договоренности оказывает свои услуги ав конторе, в которой он сам не работает и никогда не согласится работать.
ага http://avksdie.narod.ru/
кст чел, что пикчу кидал - жутко хуесосил эту контору, говорил, что сам из команды исследования сложных угроз
Потому что я начал и уже начинаю плавать в понятиях и мало что понимать. Где там по хардкору про регистры, стеки и проч. Танненбаума читал года 4 назад, немного знаю Си. Нужно что-то покороче. Книга по какому-нибудь AT&T асму пойдёт?
Хуй знает, там все вроде доступно. Можешь тут спрашивать что-нибудь конкретное, мы поясним. AT&T не нужен, это лучший способ запутаться.
> Что в виндах находится в памяти процесса до image base
А вы запустите отладчик и посмотрите memory map, так будет лучше с точки зрения практического обучения
Вся память делится на регионы, которые состоят из страниц с одинаковыми атрибутами доступа. Выше / ниже модуля находятся другие модули, паддинги и тд
Как прицепить отладчик к программе, которая через системный шелл вызывается в другой программе? Пока ничего кроме int 3h на OEP не придумал. Может, есть что-то элегантнее?
Создаешь ключик HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Program.exe. Втыкаешь туда значение типа REG_SZ Debugger="путь к отладчику (с опциями, если нужно)". После этого каким бы образом ты не запускал программу, она будет попадать в указанный отладчик. Достаточно элегантно? То же самое делается мышкой через gflags.exe из Debug Tools for Windows, вкладка Image File.
Максимально элегантно в моем случае. Спасибо! Все подобрать кейворды к Гуглу не мог.
И не OEP, а просто EP, конечно. Сами понимаете, откуда такая деформация.
>>176878
Там, вроде, Debug Tools от Windows 7 и выше. Не знаешь, часом, че там для XP виртуалка для всех интересных дел?
Или даже нахер это все, мне через реестр проще.
Вот это вот «Program.exe» указывать абсолютным путем или хватит просто названия исполняемого файла? Экзешник в PATH (или как это на Windows называется? Короче, из cmd запускается просто как file.exe).
На чем написано приложение?
> Как мне поставить условный БП на чтение памяти, если в ней такая то строка?
Никак.
Если верить PEiD, то msvc++ 6.0. Я параллельно читаю книгу Касперски искусство дизассемблирования и наткнулся на утверждение, что ввод в общем то могут на каждый WM_KEYDOWN/WM_KEYUP шифровать и как таковой у меня целиком строки в памяти и не будет
> абсолютным путем или хватит просто названия
Насколько я помню, работает и так, и так. Сам пишу просто имя, потому что писать быстрее.
> Не знаешь, часом, че там для XP
https://transfer.sh/Hr2Op/Debugging Tools for Windows (PSDK 2003 R2).msi если доверяешь или качни Platform SDK от 2003, из которого они взяты.
>>176966
> отследить обработку текста, введенного в поле ключа
Может там кастомный обработчик WM_GETTEXT? Может там GetDlgItemText?
> Как мне поставить условный БП на чтение памяти
Зависит от отладчика. Можешь поставить условный брейкпоинт, ловить его скриптом/плагином, проверять на наличие строки и продолжать дальше, если строки нет.
>ShellExecute
Дядя, а ты не знал, что она является оберткой над CreateProcess, которая в свою очередь вызывает RtlCreateUserProcess, а та - NtCreateProcess
Ты предлагаешь ему написать что-то, что поставит system-wide бряк на CreateProcess? И ты считаешь, что это проще, чем прописывание int3 по EP целевого бинаря, я правильно понял?
Почему оно сегфолтится, хоть и пишет в вывод hello?
.section .data
foo:
.string "hello"
.set foo_length, . - foo -1
.section .text
.globl _start
_start:
mov $1, %rax
mov $1, %rdi
mov $foo_length, %rdx
mov $foo, %rsi
syscall
Избейте ссаными тряпками, но плохо пока что понимание даётся. Мне бы на пальцах всё объяснить. Можно и на среднем.
>сегфолтится
вот мне тоже интересно, хотя у меня прост руки не оттуда растут небось
мимо другой ньюфак
Может ты строку не терминировал
Сегфолтится, потому что после вывода строки продолжает выполнять содержимое памяти, потому что завершить программу или хотя бы зациклить ее ты забыл.
>>177645
Вернул мне мой 2005й (но хуй вспомню, как фиксилось). Купи иду поновее (это в пятерке же?), включи английскую раскладку клавиатуры по умолчанию.
>>177661
> нахуй это надо
Если не знаешь, то и нахуй не надо. В TEB лежат данные потока, в PEB данные процесса. В TEB чаще всего ебут TIB, в котором лежат обработчики исключений, ну и TLS еще. В PEB самое нужное - база данных лоадера исполняемых модулей - можно писать свои загрузчики в обход системного или свои движки импорта, ну и т. д. Более-менее годная статья называется "исходники двухтысячной винды или wrk", что-то можно у Руссиновича в книге почерпнуть (там целая ебаная глава!).
>>177893
Огромная благодарность, аноны. Благодаря сну, вашим наставлениям и свежему взгляду всё заработало и перестало сегфоултится. И впрямь, нужно было просто вызвать sys_exit. Ооо... Это потрясающее чувство, когда всё компилируется, как надо. Благодарю. Продолжу вникать в удивительный мир ассемблеров.
Базонезависимость как таковая не нужна. Хотя труда большого это не составит: обычно компилятор использует jmp/call near, те нашу дельту по сути. Таким образом остается отбиться от обращений по конкретным адресам, ну и по мелочи пофиксить.
Я хочу целиком отреверсить группу экзешников суммарно примерно 700 кб как раз. До сих пор не взялся.
Слишком дохуя, а откуда начинать - не совсем ясно.
То есть, если я ловлю какой-то интересующий меян кусочек брейкпоинтом, то с поправкой на ветер понимаю, что происходит, что вычисляется. А общая картина с кучей сисколов и хардварных обращений всё равно от меня уходит.
Нет, и не мечтай.
CreateFile('\\.\PhysicalDrive0',GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
Окей, спасибо. А какими ассемблерами вы тут пользуетесь?
Можно скинуть нужный EXEшник в папку system32, переименовать в sethc.exe этлт файл, сэмулировать нажатие 4 раз шифта и все.
Мог бы обратиться к данным через дельта-смещение для большей труевости.
Просто берёшь и запускаешь от админа. А если ты пишешь вирус, то шёл бы ты нахуй отсюда.
А ты познавательно иди нахуй, выродок.
Нет, можно из памяти или даже из самого стека.
push dword[0x12345678]
push dword[eax]
push dword[esp+0x08]
И даже:
sub esp, 4
mov dword [esp], 0xdeadbeef
И даже:
sub esp,0x100
mov eax,esp
invoke memcpy,eax,somedata,0x100
Да он питуз. Если система предоставляет возможности для унижения юзверей, почему бы этим не воспользоваться? Если посреди поля ты найдешь тысячу рублей, ты заберешь ее себе или отнесешь в милицию?
кст стоит добавить, что создание верусов крайне развивает твой скилл, ибо это так или иначе андоки и внутренности
// пс, любой не пес в ав конторе имеет блэк бэкенд. Пруфы затеряны в анналах архивов некоторых сайтиков нулевых годов.
Я обычный пользователь, которому даром не нужны ни вирусы, ни антивирусы, базы которых из-за вирусописателей бесконечно пухнут.
Можно ли проект писаный на делфи билдере вернуть в делфи билдер?
Так ведь можно. IDA/IDR, от месяца до полугода жизни, и все вернется в исходники своя.
Я просто с постановки вопроса охуел.
Но почему так долго и почему руками?!
Ведь это не шифрование. Это перевод с одного языка на другой. Сложные команды в простые. Почему нет автоматического переводчика из простых команд в сложные? К тому же - есть куча разработок периода 98-10, которые никто повторять не собирается, но они нужны на индастриале как воздух. Неужели никто не заинтересован в создании универсального вскрывателя да хотя бы для того же борланда. ТАм же тьма тьмущая проектов писано.
Было такое, для вижуал васика делали, ну и где сейчас те поделки? Упростив копание в говне мамонта, ты отнимаешь краюху хлеба у мяса из бодишопа. А так - да, технологии позволяют так восстановить исходник, что он после компиляции байт в байт совпадёт. Но это нужно садиться и год дрочить разные версии билдеров-хуилдеров. Тем, кто осилит декомпиляцию, этот сизифов труд неинтересен.
Автоматика существует, есть годные энтерпрайз двиги, которые неплохо сворачивают весь мусор, но однозначно получить исходники незя, это вам не шарп
Просто ты недозрел ещё до таких дел, ну так это пройдёт, как и твой энурез с влажными фантазиями. В начале 00х были полноценные декомпиляторы для васика и жавы - потому что сами компиляторы были таким дном, что можно было легко выявить дюжину шаблонов и конечным автоматом переводить байт-код обратно в сорцы. То, что у борланда выдаётся за оптимизатор, в гцц называется -O0, так что он от байт-кода недалеко ушел. Потеряется только всякая требуха типа имен и комментов, да и то не всегда, а когда нет отладочных символов. Алгоритмы в своё время вытаскивались на раз.
> для вижуал васика делали
Никуда не делось: vb-decompiler.org Но оно далеко не все восстанавливает, и это не всегда читабельно, и это для Visual Basic, который на каждый чих дергает рантайм.
>>188370
Двачую этого. Только не совсем так: компиляция в общем случае необратима. Есть частные случаи, и для них есть решения от совсем ручных до полуавтоматических. И да, можно сравнить с поиском прообраза хэша: так же, как тебя устроит любая коллизия, тебе не нужен изначальный код, тебя устроит любой код, который будет давать то же наблюдаемое поведение. Но все равно все очень плохо.
>>188372
> есть годные энтерпрайз двиги
Ой, надеюсь, ты не про авастовское говно, которое они тут недавно зарелизили?
>>188374
> Алгоритмы в своё время вытаскивались на раз.
Они и сейчас вытаскиваются. Проблема в том, что сейчас все чаще нужны не алгоримты, а, допустим, подробная документация по взаимодействию с железкой, когда на входе у тебя только даташит со шлаком от маркетологов и ебаный бинарь размером метров 40. А внутри китайцы в очередной раз изобрели ОС.
Макроса нет, сделай табличку. Там 3 ебаных бита, 8 комбинаций, руки не отвалятся.
Оно работает через такую жопу, что проще игнорировать его, чем заставить работать нормально в современной ОС с ASLR, даже еще и с кастомным загрузчиком PE, который ты, видимо, пилишь.
Мне по учебе в вузике нужно написать драйвер для Windows, который будете иметь возможность:
1) получать/отправлять значение от консольного приложения в user mode
2) записывать/считывать значение в MSR регистры процессора
Для Линукс написание такого драйвера (модуля ядра) проблем у меня не вызвало. С Windows всё сложнее, не могу разобраться в сэмплах на сайте майкрософта, книги по драйверописанию уже устарели.
Короче, спасите, умираю.
Посоветуйте инфы, чтобы разобраться.
А ещё лучше, напишите драйвер за меня (у шарящего человека это и 30 минут не займет), а я 1500р перешлю за работу на карту.
Или посоветуйте, где за деньги можно попросить такое сделать, потому что на Workzilla и Fl.ru за 1500 рублей никто не нашёлся
1) DeviceIoControl из юзермода. В кернелмоде DriverEntry + обработчики irp. Вот простенький курс blagin.ru/sozdanie-drajverov-chast-4-obmen-dannymi/
2) RDMSR/WRMSR + интел мануал
А че за вузик если не секрет? Какая кафедра/факультет, какой курс
// не товарищ майор, интересуюсь, где же в наш 2к18 с досом не работают, а все же пилят че-то более менее
.in - это уже не васм.
Посмотри выступления с конфочек, и будешь примерно представлять, что читать. Типа такого: https://www.youtube.com/watch?v=fWqBmmPQP40
Извините, промахнулся тредом.
у меня не получалось понять как хранятся данные. банальным АртМани нужное значение получить не удалось. Спать не мог одно время, как оно меня бесило
Еще не поздно.
О, спасибо
Деньги (и, вроде бы, цены тоже) в 64-битных интах, в сотых долях копеек (т.е., в 10000-х долях того, что отображается): наличных 1234 -> 1234 * 10000 -> 12340000 -> 0000000000bc4b20 -> 20 4b bc 00 00 00 00 00. Ковыряться лень, игру не осилил, сложно.
Я же тебе расписал специально. Умножаешь, переводишь хексы, хексы задом наперед (little endian у нас), байтики ищешь (в том же OllyDbg View->Memory, правой кнопкой, Search, байтики, Entire block, Case sensitive или прямо инт после умножения в каком-нибудь Cheat Engine). Судя по адресам, оно где-то в куче.
Готового ничего в Windows API нет, но можешь из msvcrt.dll дернуть strtol. Или парси вручую. Обнуляешь какой-нибудь регистр. Берешь очередную шестандцатеричную цифру, преобразуешь ее в 4-битное значение (0..15) из '0'..'9' в 0..9, а 'a'..'f' и 'A'..'F' в 10..15 (cmp, sub, можно xlat и табличку). Если встретится не шестнадцатеричная цифра - обрабатываешь ошибку. Получив цифру, сдвигаешь свой регистр влево на 4 бита (shl) и кладешь в освободившиеся биты (or, add - похуй) свою цифру. Повторяешь, пока не кончится полученная строка или не встретится невалидный символ.
>>191874
Блять, а 64-битные числа и десятитысячные доли я, наверное, сам придумал. Все открыто лежит, просто не в тех единицах, что отображается. Более того, в каком-нибудь cheat engine с помощью поиска по increased/descreased ты бы и сам все это быстро нашел, ничего не зная и безо всяких IDR и отладчиков.
нет, я искал и ни раз
За версию либы отвечает WOW64, который подгружает 32-битную библиотеку длоя 32 битных приложений.
> если вот вдруг мне захотелось 32 битный kernel32 в своём 64 битном процессе?
То однозначно лососнешь тунца.
32-битные либы к 64-битному приложению подключать нельзя.
>32-битные либы к 64-битному приложению подключать нельзя.
вот тут вы не правы
по меньшей мере ручками можно впихнуть, затем свапаемся на x32 и погнали
>затем свапаемся на x32 и погнали
Как ты себе это представляешь? Проц переключать может только ОС,указатели, структуры и прочую поеботу нужно конвертировать и так далее. Не знаю как в люнупсах, но винда проксирует только очевидные ядерные вызовы, все остальные либы тупо скомпилированы в двух версиях, и разделяют лишь ресурсы.
Хотя чё то сам посидел подумал над своим вопросом. Раз адрес возврата в стеке, то без разницы, какой будет image base, так? Собсна поэтому и релокации не нужны для вызовов функций?
Адрес возврата в стек толкает процессор, он абсолютный адрес всегда знает. А релокации для jmp/call не нужны именно потому, что они ip-relative, а ip процессор опять же знает.
Сейчас перепроверил указатели, обнаружил 16-bit alignment. А мне нужно 32 для vmovdqa.
>Как быть?
Гугли директивы своего компилятора если обьявляешь статически (__declspec(align(#)) у мокрософта/__attribute__((aligned(#))) на прыщах и шланге)/используй _mm_malloc с выравниванием, если выделяешь динамически.
Что там куда не переностися, если результат умножения двух 64-битных чисел всё равно 128 бит.
div с 64-битным регистром делит 128-битную пару rdx:rax на этот регистр, кладет частное в rax, остаток в rdx. Если частное не влезает в rax, происходит печалька. 0x5000000000000002f / 0x0a = 0x8000000000000004, остаток 0x07. Покажи скриншот отладчика. Уверен, что ничего не портишь после деления?
Спасибо огромное, тебе. Помог разобраться. У меня ведь и впрямь до этого в rdx всякая хрень лежала. Ну, если грубо говоря, как на одном из пиков, где адын в rdx. Я отдельным модулём проверяю работоспособность, потом буду это вписывать в нужный код. Везде про какие-то расширения регистров пишут и сужения странные. А так нормально вроде. Сейчас сяду писать счётчик цифер. Спасибо, ещё раз.
Ты никогда Ольку что ли не видел, залетыш? Байткод, дизасм, регистры, стек, дамп памяти, ничего лишнего же. Пиздец, я натурально хуею с местной публики.
цы, стандартный интерфейс олли же. + помогает в отладке, чтобы проверить, что в памяти то, что должно быть.
Вот вроде и морду к радару прилепили, а он как был уебищным консольным говном, так и остался.
Как я понимаю, если я захочу запилить исполняемый файл на машинном коде, не подходящий ни под одну широко распространённую операционную систему, мне придётся писать свой собственный ассемблер и ломать глаза об многотонные талмуды уровня "Intel® 64 and IA-32 Architectures Software Developer’s Manual"?
Мне кстати гуй не нравиться, неудобный пиздец, ебучие макаки со своим qt, фрон тэед на gtk был лучше в сто раз, но он умер. Перекатился обратно в соснолечку, мне не привыкать
Из ассемблеров бери fasm, на нем целая колибри и пара операционок подохлее написано. Талмуды от интела кстати неплохие, но только как справочники юзать. Их раньше даже в бумаге присылали совершенно бесплатно, но я при переезде проебал где то. А жаль, сейчас бы не отказался бумажную копию заиметь.
И вообще кури https://wiki.osdev.org/
Вот за это вообще адовое спасибо. Не думал, что даже про такие основы могут быть какие-то вики.
Может и про электротехнические основы приёмо-передающих устройств есть своя вики? Типа, "как создать свою собственную амплитудно-частотную систему кодирования и разработать сигнальные созвездия с нуля"?
> настойчиво упоминается Raspberry, но мне всё-таки хотелось бы на чём-нибудь Интеловском начать
Не зря упоминается (хотя конкретно Raspberry - то еще днище с неполноценной документацией). Пол ARM bare-metal писать... ну не проще, но хотя бы логичнее, гораздо меньше всякого ненужного легаси из 80х.
> И непременно всё на языке ассемблера.
Категорически не рекомендую. Потратишь время на пердолинг в ассемблер вместо собственно создания ОС. А так, бутлоадер написал, обвязку всякую, для которой интринсиков нет, и вперед, хуячить на сишечке.
Ну написать ОС, хоть и довольно примитивную реально, а вот ИИ нет.
хотя судя по его вопросам он не представляет размер трудностей
>Пол ARM bare-metal писать... ну не проще, но хотя бы логичнее, гораздо меньше всякого ненужного легаси из 80х.
И то не сказал бы, бойлерплейт "запусти все режимы выполнения arm v8, чтобы и с гипервизором и с режимом "анальный огрод"" примерно такой же как real->protected->long выходит.
Вот кстати, анончик, объясни мне, на OSdev читаю про "войти в long mode":
lea eax, [es:di + 0x1000] ; пихают адрес es:di +1000 будущей директории в запись PML4
or eax, PAGE_PRESENT | PAGE_WRITE ; хуярят туда же флаги для этой записи
mov [es:di], eax ; сохраняют запись
А потом поинтересовался какой же формат у этой записи, и вижу пикрелейтед.
Где видно что адрес располагается в битах с 11 по 31, а они просто его хуйнули без всяких сдвигов.
Это что за уличная магия такая? Или это little endian так работает, что mov 00000000, FFFF = FFFF0000?
Нет, little endian тут не при чем. Вот тебе же написали:
> 4 kb aligned address
Раз адрес всегд выровнен на 4K (212), значит в его младших 12 битах всегда нули. А раз там нули, то их можно как угодно абузить под флаги - железу это не помешает прочитать адрес с нулями и флаги отдельно.
> все возможные ниши уже заняты
Наоборот ниши освобождаются: Windows следит за тобой, жрет память и обновляется без спроса, от релиза к релизу становясь все хуже, Android следит за тобой, садит батарейку и на многих девайсах не получает даже секьюрити-апдейтов, про iOS и политику Apple можно только молчать. Мир замер в ожидании принципиально новой ОС.
Это в качестве шутки было. Впрочем, не думаю, что осесрач тут будет уместен, так что закончим на позитивной ноте "Все ОС говно".
Это понятно.
Я про то что
[es:di + 0x1000] - 16 разрядное число и lea eax, [es:di + 0x1000] должно по идее в младшие биты идти, а оно без каких либо телодвижений в старщие пиздует?
А, блядь, все, понял. Получается, в записи адрес равен 1 (0x1000 - это как раз 12 нулей и тринадцатая 1 ), а хуйня под флаги -нули.
Вот я бака. Спасибо, сажа-кун.
Не, это я знаю, мне интересно схуяли там ebx если в стандартном прологе ebp.
хз, в 32+ битных ОС регистры используются как регистры общего назначения, а не как в 16 битных досах с ограничениями. предположу, что некоторые компиляторы из исторических соображений используют ebp для этих целей, но по факту используй какой хочешь кроме esp и eip
>если в стандартном прологе ebp.
Каком еще стандартном прологе? Стандартным является ABI - что компилятор обязуется передавать в определенных регистрах и возвращать результат в определенных регистрах. В остальном компилятор дрочит так как ему больше нравится.
кык. чёт хуйня какая то. что за компилятор? может быть, это обфускация, а может это неудачная попытка оптимизации по скорости или по размеру
Короче там какой-то крипт, ибо кроме main там весь .text - недекомпилируемое месиво.
Понял уже что лажанул, наверно надо HeapAlloc использовать. Я только учусь. Пишу hex-поисковик, который будет искать hex-строку с пропуском любого кол-ва байт и записывать смещения в файлик. Точнее, уже написал, только функция ReadFile читает по одному байту из файла и поиск в файле 85Mb занимает около двух минут, значит в файле 850Mb поиск будет 20 мин. Это из-за того что чтение по одному байту?(наверно) Вот и решил увеличить буфер для чтения. Но сколько его сделать? Какой оптимальный буфер?
Неправильно понял. Выделяет, сколько попросишь. Алсо, оно почти не содержит магии, просто обертка над обычной кучей для совместимости.
>>201304
> ReadFile читает по одному байту из файла
Да, каждый ReadFile - это поход в ядро через несколько презервативов, поэтому и медленно.
Осиль memory-mapped IO (CreateFile/CreateFileMapping/MapViewOfFile), отображай по паре сотен метров за раз (ну или больше даже, если у тебя x86-64), пусть система ебется с чтением файла, а ты ищи свои байты.
486x360, 1:23
Не надо грязи. Функция GetWindowTextLength в Хеллоуворлде без надобности.
> Какой оптимальный буфер?
Размером с кластер файловой системы, поскольку именно столько за раз ось и считывет. Все это гуглится на раз.
Блять, проверил, действителньо печалька происходит. Могли бы сделать сохранение верхней части результата и не падать, блять. Хотя да, бесполезно. Придётся ебаться с нормализацией.
Ось-то считывает, только ты можешь у ядра попросить 64к за раз, а можешь мегабайт за раз. И потратишь на это в обоих случаях один сисколл.
1280x720, 1:18
Сделал
invoke CreateFileMapping, eax, 0, PAGE_READONLY, 0, 0, 0
invoke MapViewOfFile, [hMapFile], FILE_MAP_READ, 0, 0, 0
Вроде норм, на видео поиск по файлу 800Мб.
>тайпал
>тайпал
>тайпал
>тайпал
>тайпал
Пиздец, подвороты своим новоязом уже эмигрантов с брайтона переплевывают.
Да не, наоборот пытался быстрее, чтобы размер видео был меньше, спать хотел, ещё поле ввода табом не переключается, хотел как лучше а получилось..
Ща обработчики ошибок доделаю и скину програмку.
Да чё ты, мэн, нормально же токили, обычный вопросик аскнул, а ты завёлся. Чиллься.
Ты кусок ебаного дебила, чтение в любом случае идет блоками, кластерами. Хоть опережающее, хоть опаздывающее, как у тебя.
>>203125
Говна въеби, шалава малолетняя. Учить она еще меня будет как на двощах общаться.
>>203134
Научись слепой печати, это не долго (хоть и не оче приятно первые 2-3 месяца) и сильно повысит качество твоей жизни.
В моём случае лучше через файл маппинг, потому что ещё есть "проблема пограничного значения", это если я ищу строку 12345678 и 1234 в конце текущего блока, а 5678 в начале нового блока, это тоже обрабатывать надо, а это пипец. Если прога совсем низкоуровневая, то да, надо кластерами, спасибо.
После того как строка найдена, увеличиваю счётчик:
mov ebx, [FoundCounter]
inc ebx
mov [FoundCounter], ebx
по окончанию файла конвертирую значение в ascii. Но значение то шестнадцатеричное. Как лучше сделать? Преобразовать готовое значение в десятичное(как?), или сразу как-то счётчик обрабатывать?
Вообще, в принципе, IDA не так уж и нужна, мне бы что угодно, способное дебажить 16-бит под форточками.
debug.com
В твоем случае есть проблема "32-битное фрагментированное адресное пространство и файл на полтора гига". Для учебной проги решение норм, а вот для реальной все равно нужно делать регионы какого-то максимального размера, и ремапить их по необходимости.
>>203413
wsprintf %d или вручную делением на 10.
>>203446
> что угодно, способное дебажить 16-бит под форточками
Билд DOSBox со включенным дебаггером? Но лучше все же Turbo Debugger, который уже посоветовали.
>чтение в любом случае идет блоками, кластерами
И это значит, что буфер должен быть размером, кратным кластеру. А не всего с один сраный кластер, коий по дефолту 4кб.
Функции, которые работают с ресурсами, пойдут в ресурсы через директорию ресурсов, GetProcAddress() пойдет в экспорты (т.е., если у программы, например, плагины, и плагин-апи лежит в .exe, и ты как раз .exe распаковываешь, все сломается).
Есть где нибудь полный список таких подводных камней, или самому догадываться придется исходя из различных возможностей ОС и процессов в ней?
И можно ли со спокойной душой спокойно коверкать IMAGE_FILE_HEADER, IMAGE_NT_HEADER, и остальные заголовки в PE под IMAGE_BASE, если я например хочу, чтобы образ, восстановленный из дампа, не запускался без ручного восстановления? Или в винде есть какие нибудь популярные механизмы, которые в рантайме обращаются к этим заголовкам?
>>204923
Вряд ли список найдешь где-то. Есть спека на сам PE-формат, но реальное поведение лоадера не документировано и на протяжении истории Windows менялось не раз. И не только поведение лоадера - например, в 9x Explorer хотел, чтобы ресурсы лежали в начале .rsrc, а если его не ублажить, не показывал иконку и версию в свойствах файла).
> Или в винде есть какие нибудь популярные механизмы
Все те же, что и выше - чтобы добраться до DataDirectory, нужно офсеты, а офсеты как раз в этих заголовках. Возьми IDA, настрой подгрузку символов и смотри. Если DataDirectory твоей программе не нужна, можешь портить, в принципе.
Причём работает даже когда следующая структура начинается через 20 байт. Почему так?
Точно. Спасибо, подозревал что что-то не так с этим ULONG_PTR.
Тогда вопрос: какой размер указывать? Если прогу запустят на 32-битной ОС?
Тьфу затупил
Рудакова почитай, также есть еще Пирогов по асму и дисасму, тоже пойдет.
Да, кратному. Спасибо что уточнил.
А, и ещё: как в FASM, в формате MZ
1. Явно указать конец сегмент?
2. Инициализировать сегменты один за другим, строго в том порядке, как я их указываю в листинге?
inb4 нахуя мне это - предполагаю, что неправильный OEP собьёт с толку дизассемблеры, делаю что то типа протектора в образовательных целях.
Возможно, не шарю в тлс-каллбэках. Как ты изменишь адрес возврата из виндовой функции в то время когда она уже выполняется? Это сторонним кодом наверно надо с переполнениями стека, а это уже будет вирус. Может попробовать сделать имитацию этой функции, сделать её частью своей проги, а уже в ней делать адреса какие захочешь.
Или я короче хз. Просто предположил что функция сама положит нужный адрес entry point.
Это так? Потому что чисто логически, если в той ячейке стека будет лежать адрес входа в функцию, то тогда call функции будет перед entry point.
TLS коллбэк не из точки входа вызывается, он вызывается загрузчиком судя по всему, где то из ntdll, над стеком точка возврата - не ОЕР. Мне надо понять, как загрузчик после выполнения TLS коллбэков передает управление на ОЕР, или в какой структуре, управляемой загрузчиком, на момент обработки TLS, находится ОЕР
> Как ты изменишь адрес возврата из виндовой функции в то время когда она уже выполняется?
Так мой же код. (&ModuleHandle)[-1] = newReturn;
Так в этом нет смысла. Ты же всё равно не сможешь изменить виндовский код без хакерских приёмчиков. Ну допустим, у тебя винда поместит твою прогу по одному адресу и передаст ей управление, у меня по другому адресу. (очень поверхностно себе это представляю). Ну и если ты, каким то образом умудришься указать явный энтри пойнт, то у меня будет выполняться какая-то непонятная херь и краш, бсод. Какой смысл? Или у тебя задача всё же другая?
Хотя.. наверно можно. Будем ждать профи.
>умудришься указать явный энтри пойнт, то у меня будет выполняться какая-то непонятная херь и краш, бсод
Это конечно херня. Но как сделать изменение результата функции до того как этот результат получен?
>Какой смысл? Или у тебя задача всё же другая?
еще раз, я пишу что то типа протектора/упаковщика в образовательных целях, то есть на вход мне подаётся РЕ-файл. С целью противодействия дизассемблирования мне показалось поправьте, если не прав неплохой идеей в ходе упаковки в OptionalHeader ставить кривой OEP ОЕР+const, чтобы дизассмблер поперхнулся на нем, предоставив ачкеру на обозрение какую то кашу. Но вот TLS коллбэк, написанный мной и вшитый в упакованный файл, выполняется загрузчиком да? до передачи управления ОЕР, и в нем я хотел бы проста тупа взять и ОЕР-const сделать, чтобы после TLS callback'ов управление передалось на настоящий код. Вот и вопрос, я вижу в стеке ложный OEP, считанный загрузчиком из OptionalHeader'а, но не знаю как до него добраться. Не знаю, через какие структуры к нему пролезть, РЕВ, TEB там, вот эти ребята.
немного дзена для атмосферы
ЯННП. Покажи исходник.
>>206876
>>207250
Из TLS патчить в хедерах точку входа бессмысленно. Она как минимум задолго до вызова твоей TLS-функции EP кэшируется в TEB->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList->EntryPoint. Но и там ее править бесмысленно, потому что в контекст треда задолго до LdrpInitialize, еще когда тредик создавался в NtCreateUserProcess, положили эту самую EP, а RtlUserThreadStart положил ее в стек, в самое начало.
> Лучше мне подскажите как менять позицию курсора в поле edit
Если права есть, то можно отправить EM_SETSEL с параметрами, равными длине текста. Но это работает только для стандартных Edit. Для рандомного поля ввода шли нажатиями.
> всё равно работет только с размером 28 почемуто
Документацию читать пробовал? Размер 24 - это размер KEYBDINPUT, а посылать надо INPUT, и размер тоже для INPUT указывать, а это на 64-битной системе вообще 40, потому что там union, содержащий и другие, более длинные члены.
Насколько плохим является решение из TLS callback'а прогуляться по стеку пару 0хтысяч байт вверх и вниз в поиске VA OEP с целью отнять константу? Такие подходы практикуются вообще?
> пару 0хтысяч байт вверх
Ну если уж делать так, то стоит искать весь CONTEXT целиком, проверить, что Eip/Rip там попадает на RtlUserThreadStart (в XP не экспортируется), Esp/Rsp в регион стека, а в Eax/Rax будет лежать адрес (по крайней мере, в 7 еще лежал) - так чуть-чуть понадежнее. Но гораздо надежнее похукать ZwContinue, туда прилетит готовый адрес CONTEXT аргументом, а тебе останется лишь снять хук и пропатчить Eax/Rax в контексте. Но в целом это будет не более сложно для реверсера, чем обычная расшифровка в TLS кода по EP.
Вроде разобрался.
Указывать нужно размер самой большой структуры INPUT, у меня это MOUSEINPUT, хоть я и использую KEYBDINPUT.
Так как у меня программа 32-битная, то этот размер 28 байт. Но для 64бит он вроде 32 должен быть.
И вообще, зачем указывать этот размер, система сама не в состоянии его определить? Дичь какая-то.
То есть, счётчик увеличивается на единицу в цикле, как только он делится на три то выполняется условие. Как лучше сделать?
К сожалению, только делением. Но ты можешь сделать два счетчика - один будет считать по единицам, а второй ты будешь на каждый третий раз сбрасывать.
>>207676
> 4 байта указатель
Проиграл. Нет, заголовок структуры - это просто имя, содержимого структуры оно не определяет, места не занимает.
> 8 байт на пике
Только в 64-битной ОС.
> Указывать нужно размер самой большой структуры INPUT
Я тебе уже писал, что указывать нужно размер INPUT, он всегда одинаковый. Да, по сути это размер dwType + размер MOUSEINPUT, потому что она самая большая.
В 32-битной ОС размер INPUT: 4 байта dwType, 24 байта MOUSEINPUT (там все 6 полей по 4 байта), всего 28. Размер KEYBDINPUT: 2 ворда + 3 дворда = 16 байт. И не забывай, блять, про dwType в INPUT, он не часть union, он должен быть всегда.
> И вообще, зачем указывать этот размер, система сама не в состоянии его определить?
Представь, что в Windows 11 в INPUT добавляют TOUCHINPUT, и его размер больше MOUSEINPUT, из-за чего размер всей структуры INPUT меняется, и SendInput вместо второго и последующих элементов массива читает мусор. Но Microsoft позаботилась о тебе: если твоя (скомпилированная до этих изменений) программа передаст старый размер INPUT, система увидит старый размер и будет знать, что это старый формат INPUT, который умеет только в mouse/keyboard/hardware, и ничего не сломается. А новые программы, собранные с новым SDK смогут использовать добавленные возможности.
Да причём тут ОС то ёптабля, ты мне первый раз написал про ОС, у меня сразу каша в голове>>205840.
Думаю тут всё проще: пишешь 32-битное приложение - указываешь один адрес, пишешь 64-битное указываешь другой. А компилировать и запускать можно хоть на 128битной ОС.
Указатель имелся ввиду dwType, чтобы лишних скринов не делать.
Раздели var1 на 3, запиши результат в var2, var2 умножь на 3 и сравни с var1. Если значения равны, то число делится, иначе ты потерял точность из-за округления интов и оно не делится
Лол, в асме попроще, там после команды div результат в eax, остаток в edx. Ну и если edx после деления 0, значит число делится. Просто ещё есть проверка на чётность, она ещё проще - test eax, 1, если результат 0 то число чётное.
Да, извини, я имел в виду 32-/64-битные приложения, а не ОС. Алсо, я не вполне понимаю, зачем ты вручную считаешь. В Си есть sizeof, в фасме есть sizeof.имяструктуры, в масме тоже есть SIZEOF имяструктуры.
Тогда давай я тебе ещё пердак разогрею. Командой тест можно проверять не только чётность, но и делимость на числа степеней двойки - 2,4,8,16,32,64...
Вы же понимаете что такое цикл? То есть, чтобы выйти из цикла когда счётчик будет равен 512, нужно проделать 3 операции по пять асмовских команд 511 раз.
Считаем, 3x5x511=7665 ненужных вычислений. НО! этот цикл то не один, а их хз сколько. Даже взять миллион, это уже 7 665 000 000 ненужных операций. И это я ещё не переводил в такты процессора.
ОЙ блять. А выполняющаяся программа в памяти, весом в 2гб, имеющая уже скажем 200 таких циклов, будет к ним обращаться снова и снова, пока она не будет завершена. Тут счётчик вообще улетает в космос.
Скажу просто - КПД 0,0001%
Знаете почему не применяется? Догадываетесь? Потому что тогда всякие java-пограмисты станут нахуй никому не нужны. А почему так происходит? Догадываетесь? Потому что дядькам на верху нужно чтобы всё так и было.
Если ты лох вафельный, изучай только асм!
(Дополнение)
А вот можно ли поделить на 3 быстрее команды div интересно узнать. Мб есть какой-нибудь трюк, вроде шифта битов и прибавления числа, как при умножении
k = 5, m = 73
k*m = (m<<2)+m
А анализ алгоритмов это что по-твоему?
Да сам проигрываю чё я тут спьяну навычислял. Но доля правды в этом всё же есть: 1 будущее за робототехникой 2 Ненужные операции потребляют энергию 3 аккумулятор сейчас проблема и всегда будет проблемой
https://ru.wikipedia.org/wiki/Признаки_делимости#Признак_делимости_на_3
Наверняка еврейские умы уже пытались. Но всё равно попробовать стоит, потому что ситуации бывают разные. В связи с этим вопрос: Где взять хороший справочник команд? С опкодами и циклами. Можно в шапку добавить. Помню был такой в dos-варианте.
Вот, например, анончик который занимается изучением ОС(уже наверно сам понял). Зачем ему заниматься изучением велосипеда, если можно заняться изучением ОС мобильных девайсов, дизассемблировать их, убрать лишние команды и тем самым увеличить время до перезарядки девайса. Это же реально можно продать, и сделать это намного реальней чем пилить свою ОС.
Может быть я тут раскрываю секреты полишенеля, но я бы трезвый к этому не пришёл бы, или пришёл бы но не скоро.
> Ненужные операции
Либо ты делаешь их явно, либо у тебя CISC, и ты все равно их делаешь, только уже в микрокоде. Потому что "ненужность" каких-то операций - это лишь твои фантазии.
>>208289
> Где взять хороший справочник команд?
Пишешь в гугле: Intel SDM. Второй том - справочник. С опкодами и псевдокодом каждой инструкции.
Вобщем решил подойти творчески, с душой, и не дать пользователю сделать такую ошибку. А заодно и автоматически вставить дефисы после каждого байта, хоть вручную хоть после копипасте. Но вот дефис должен вставляться каждый третий символ. И не знаю что лучше: заранее эти дефисы понаставить, или же чтобы всё было одновременно со считыванием строки поиска.
> Ну короче щас застопорился на этом делении на три
while (1) {
digit = get_digit();
check_digit(digit);
if (first_digit) {
store(digit);
} else {
store(digit);
store('-');
}
first_digit = !first_digit;
}
Где тут деление на 3? Зачем?
Млин, ты прикалываешься? Алгоритм такой:
1 при любом изменении строки edit программа прерывается на обработку
;-----обработка
2 создаю область памяти = столько сколько символов в строке
3 создаю вторую область памяти
4 записываю изменённые значения из первой области во вторую
5 выдаю в строку edit вторую область памяти
И как мне быть? Сразу записать во вторую область дефисы, или же это делать одновременно со считыванием данных из первой области памяти?
Ну ясно-понятно что вторую область создаю размером уже с учётом дефисов(это легко).
При чём, при таком алгоритме ещё нужно чтобы сами дефисы были прогой распознаны и вставлялись во второй раз.
Меня опять несёт, сори, сори, сори...
1 Считывать каждуй байт из области 1 и проверять на делимость на три, чтобы вставить дефис
2 Заранее понаставить дефисов в месте: адрес второго блока памяти +3. И потом сверять каждый байт во втором блоке памяти перед копирыванием.
ВОТ Я НЕ ЗНАЮ!! КАК СУКА ЛУЧШЕ СДЕЛАТЬ!
Вот по трезвому опишу что мне нужно, без всяких этих
Пусть у меня в поле edit уже есть два символа 12, я ввожу третий символ. Поле edit посылает сообщение что оно изменилось. После чего создаётся два блока памяти, один размером три байта, другой рамером 4 байта(пять с завершающим нулём, но это не важно).
Функцией GetDlgItemText получаю символы из поля edit в первый блок памяти, там будет три байта - 31,32,33. Теперь мне нужно сделать так чтобы во втором блоке памяти была следущая строка байт -31,32,2D,33(2D - дефис). Затем функцией SetDlgItemText посылаю в поле edit строку байт из второго блока памяти. Уничтожаю блоки памяти.
Ещё есть тонкость в том, что когда я после ввода 123 я введу 4 то в первом блоке памяти будет 31,32,2D,33(уже с дефисом).
Просто будет выглядеть классно, профессионально и вам может пригодится. Помогите
>А вот можно ли поделить на 3 быстрее команды div интересно узнать. Мб есть какой-нибудь трюк, вроде шифта битов и прибавления числа, как при умножении
Если в плавучке - то быстрый обратный корень*2
TLS_OEP_OFFSET - не нулевая константа
Всё, отбой тревоги. Я наебал компилятор.
Как это не может? В заголовке PE или ELF есть адреса. А уже ОС располагает с этого адреса.
hint: страничная виртуальная память
> А если речь идёт о реальном режиме с сегментной адресацией?
Тогда еще проще. В заголовках есть таблица поправок. Каждый раз, когда ты делаешь:
mov ax,CSEG
генерируется поправка. Когда файл грузится, MS-DOS проходит по списку поправок и втыкает туда реальные значения сегментов. А внутри самого сегмента адресация "абсолютная", т.е., [ds:10] всегде ds*16+10, вне зависимости от того, куда тебя загрузили.
О, спасибо за разъяснения.
>Пикрелейтед не работает
Ты
>>include \macro\proc32(64).inc
забыл.
алсо, proc - это обычный макрос-сахарок, который за тебя аргументы по ABI разруливает.
Без него - пердоль руками меточки и ручками по википедии, согласно соглашению твоей операционной системы/разрядности работу с регистрами пердоль.
> Какой корректный синтаксис в FASM для создания процедур?
Никакого. Макросов для для 16-битного кода нет. Можно, конечно, адаптировать proc32/64, про которые написали выше, но особого смысла в этом нет, ибо 16-битных код нахуй никому не вперся в 2018.
> Какой корректный синтаксис в FASM для создания процедур?
Никакой. Макросов для для 16-битного кода нет. Можно, конечно, адаптировать proc32/64, про которые написали выше, но особого смысла в этом нет, ибо 16-битных код нахуй никому не вперся в 2018.
Во-первых:
https://en.m.wikipedia.org/wiki/X86_calling_conventions
Во вторых, нет, используй call. Функции и процедуры делаются с помощью меток и передачей параметров по соглашению о вызовах.
ССАЛ Я НА КАНВЕНЦИЮ))))))))))))0 А НА КАЛЛ КАЛ КЛАЛ)))))))))0000000000000
Получается, вызов любой процедуры должен быт организован таким, и только таким способом?
В статье описана передача параметров через стек. При этом, на различных ресурсах, упоминается передача параметров через регистры. А что, если пользователь решает пойти именно таким путём? При этом мы не знаем, в каких именно регистрах он передаёт параметры в процедуру.
>При этом мы не знаем, в каких именно регистрах он передаёт параметры в процедуру.
Знаём. По порядку, начиная с rdi.
Это ты PUSHA(D) имеешь ввиду?
>>210488
>>210489
Получается, сама идея подпрограмм (функции, процедуры, etc) основывается на следующих строго обязательных к исполнению постулатах:
1. Определено точное количество аргументов, которые предполагается передавать в данную подпрограмму;
2. Определёны множества возможных значений для каждого из аргументов;
3. Данный аргумент может принимать значения из заданного для него множества, и только из него;
4. Подпрограмма должна работать только с теми данными, что были переданы в неё через аргументы, либо с глобально доступными данными, либо с данными, которые определяются непосредственно в ней.
5. Подпрограмма не должна изменять никакие иные данные.
6. Подпрограмма может возвращать либо какое-то одно и только одно значение, либо не возвращать никакого вовсе.
Верно?
И в таком случае, развивая мою предыдущую мысль, код вида
call _proc
, означает вызов подпрограммы "_proc" без аргументов.
В любом случае, инструкция "call" подразумевает следующие действия:
1. Сохранение адреса возврата на вершину стека: push $+4(near) или push $+8(far)
2. Сохранение смещения дна стека на вершину стека: push bp
3. Поднятие дна стека на уровень вершины стека: mov bp,sp
Блядь, я думал, что в асме швабодка, что можно как угодно крутить какими угодно значениями, что скверна абстракций высокого уровня мешает незамутнённому восприятию красоты байткода. А тут, ВНЕЗАПНО, оказывается, что львиная доля абстракций языков высокого уровня как раз таки обусловлена особенностями исполнения кода на низком уровне.
> Ясно. Вот такая конструкция сможет имитировать функционал call?
Почти. push byte недостаточно для переходов в пределах сегмента (64к), надо push word. Далее, ты не различаешь короткие и ближние переходы:
jmp @f ; short jump, 2 bytes: eb rel8
rb 127
@@:
jmp @f ; near jump, 3 bytes: e9 rel16
rb 128
@@:
Поэтому лучше сразу написать jmp near _proc. Ну и с учетом всего этого, нужно делать add ax, 6 (3 байта push, 3 байта jmp).
>>210488
> Получается, вызов любой процедуры должен быт организован таким, и только таким способом?
Нет, кодовые конвенции нужны только для взаимодействия с чужим кодом (и для предоставления API). Внутри своей программы ты можешь делать все, что захочешь. Например, если собирать сишный код с оптимизациями, компиляторы могут раскладывать аргументы в регистры, причем для разных функций в разные. Они это делают, потому что они знают, что функции не вызываются извне, а там, откуда они вызываются, информация об используемых регистрах доступна. Это тоже соглашение о вызове, но в нем компилятор соглашается сам с собой.
Чушь какая-то. Идея подпрограмм состоит в том, что есть кусок кода, управление на который передается и потом возвращается им обратно. Как именно, что оно делает, зачем, кто вызывает, как передает аргументы, передает ли вообще - всегда на совести реализации. Есть стандартные подходы, но это не значит, что можно использовать только их.
Был там, у 6.10 файлы битые. Либо не ту версию качал. Какая там гарантировано рабочая?
Сложи содержимое всех папок DISK# в одну, проверь, чтобы директория с установочником и директория, в которую устанавливаешь были без пробелов, русских букв и прочих странных спецсимволов (короче, чтобы были валидным досовым 8.3 именем), выбирай Windows NT при установке. У меня все ок.
С умножением все понятно, например 15 x 21 = 15 x (16 + 4 + 1) = 15 x 16 + 15 x 4 + 15 x 1 = 15 << 4 + 15 << 2 + 15.
Т.е. в цикле по числу битов (8 или 16) нужно сдвигать первый множитель (15) влево, а второй (21) - вправо, и при флаге переноса CF к результату (изначально 0) прибавлять сдвинутый первый множитель.
А вот деление как можно разложить?
Z80 умеет выполнять сложение, вычитание, смену знака, логические операции и сдвиги.
https://en.wikipedia.org/wiki/Division_algorithm
Обычный long division, который "столбиком, как в школе", очень быстро реализуется.
Добра и денег тебе, анонче.
Под остальные (Integer division with remainder, Restoring division, Non-restoring division) для 16-битного деления не хватает 3-х 16-битных регистров, а сохранять/восстанавливать в стеке - медленно.
Первым пиком на: ml.exe /c /coff prog01.asm
Вторым на: ml.exe prog01.asm /AT
Без /coff первый вариант пролетает, но без .com файла, читай: в нихуя.
Выручайте, пацаны. Не хочу надолго застрять у старта.
Ты можешь делить 16-битное на 8-битное, получая 8-битные частное и остаток, как сделано в x86. Или тормозить. Других вариантов у тебя все равно нет, лишних регистров тебе ни один алгоритм не прибавит.
>>210718
> /coff
Все правильно ругается, досовый формат объектников - OMF.
> Без /coff первый вариант пролетает, но без .com файла
Потому что /c говорит "только скомпилировать, не линковать", поищи там у себя prog01.obj.
Короч, тут такое дело. Я тебя слегка наебал, надо было, видимо, выбирать второй пункт (MS-DOS/Microsoft Windows) и отказываться от виндовых файлов (наверное), тогда оно устанавливает правильный LINK.EXE в %MASM%\BIN. И после этого у меня собрался хелловорлд.
Да, ты меня наебал. Теперь и у меня .com собрался и работает.
Инструкции тормозные, но как приятно они упрощают реализацию некоторого алгоритма, что трудно побороть соблазн использовать их.
Ты можешь хуярить как хочешь, пока не пересекаешься с чужим кодом. Но когда начинаешь пересекаться - нужно иметь какие-то правила взаимодействовать.
Связный вопрос: Как узнать какие регистры не изменит api-функция при любом результате этой функции?
Почитай ABI платформы, под которую пишешь. Например, в википедии: https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention
Должен ли был я написать об этом? Нет, не должен.
Не вижу. Папку надо открывать?
Потому что я не знаю высокоуровневых языков, в этой проге всё равно будет низкоуровневая задача. Короче, она будет мониторить сейвы игры на изменения, если изменение(сохранение) успешно то делает бэкап, если нет то выкидывает окошко поверх игры(такая задумка) и можно попробовать сохраниться ещё раз.
это не низкоуровневая задача. если тебе не принципиально это делать именно на асме, то рекомендую взять какой нибудь C# и его FileWatcher с удобной системой событий на изменение файла. если принципиально - кочай конпелятор МАСМа, ищи что в него из WinAPI завезли похожего на файловый монитор.
Потому что в CS как и в RIP/EIP/IP напрямую в x86 писать нельзя, для этого есть JMP/CALL/RET, в том числе indirect версии, которые читают целевой адрес из регистра или памяти. Алсо, запись отдельно в CS не имеет особого смысла: если у тебя фиксированный IP, ты можешь сделать far jump, а если нефиксированный, то зачем тебе вообще менять CS? Откуда ты знаешь, что в новом сегменте по текущему IP будет валидный код?
Да, процессор работает только с числами, а интерпретация этих чисел целиком на твоей совести, в процессор ничего не "вшито". Но так как людям нужно обмениваться данными, есть общепринятые соглашения о том, какой символ сопоставить какому числу. Одно из них - ASCII (128 символов), но он уже слегка нинужен, потому что есть Unicode (миллион символов, из которых первые 128 такие же как в ASCII). И да, ты можешь поиграться хоть с японщиной, хоть со старославянщиной, хоть с эмодзями, если твоя система умеет это все рисовать.
Кому не лениво - посчитайте в тактах время выполнения миллиона итераций pushf/popf.
Интересуют значения разных моделей процессоров. Нужно набрать статистику.
Если нужна программа - брошу сюда как только доберусь до компьютера. Да поможет вам инструкция rdtsc
Если тебе понадобились pushf/popf для арифметики, а не для ебли TF и других неарифметических флагов, ты делаешь что-то очень неправильно.
Кстати, в 8086 инструкция mov cs, ax была валидной.
"On the 86 and 88, but not on the C-MOS versions 80C86 and 80C88, the instruction MOV CS,op is valid and causes an unconditional jump.
The C-MOS versions, as well as the NEC V20 and V30 ignore this coding. This may also be the case on the 186 but has not been tested. The 286+ CPUs consider CS an invalid operand for this instruction and generate exception 6 (Invalid opcode).
The opcode for the MOV CS,op is: 8e [mod:001:r/m]"
Постфиксный инкркмент/декремент внутри условий.
Ты понимаешь что inc/fdec ,меняет флаги z и c ?
Неправильно сделали авторы языка Си, когда придумали постфиксные операции.
Короче, вопрос остаётся в силе - какова цена pushf/popf ?
> Неправильно сделали авторы языка Си, когда придумали постфиксные операции.
Язык делался не под x86, а под PDP, который (частично) умел в пост-инкременты. Алсо, сейчас оно в ARM отлично поддерживается и очень удобно: mov r0, [r1], #4 прочитает в r0 память по r1, а потом прибавит к r1 4.
> inc/fdec ,меняет флаги z и c
> какова цена pushf/popf
Дороже, чем сделать cmp/test заново. Но ты все равно что-то делаешь неправильно. Тащи код.
Выход: (a + x y) m
Верхние 64 бита каждого умножения и carry флаг при сложении меня не интересуют.
Был такой код:
mulx r8,r9, rsi
add rdi,r9
mov rdx, rcx
mulx r8, rax, rdi
ret
Я могу избавиться от лишнего mov, сохраняя результат умножения сразу в rdx? Может он быть source и destination одновременно? Вот так:
mulx r8, rdx, rsi
add rdx, rdi
mulx r8, rax, rcx
ret
Я пока ничего не делаю, а изучаю вопрос.
Потестировал. Вот как-то так:
rdtsc
movDWORD PTR _start, eax
movDWORD PTR _start+4, edx
movecx, 1000000
label_loop:
pushf
; nop
popf
loopnzlabel_loop
rdtsc
movDWORD PTR _stop, eax
movDWORD PTR _stop+4, edx
Выходит что пара pushf/popf в среднем занимает 100 тактов. Это очень дохуя. Придётся отказаться от их использования и лепить дополнительные проверки/переходы.
Но всё же интеренсно как поведут эти инструкции на других x86 "камнях".
Я пока ничего не делаю, а изучаю вопрос.
Потестировал. Вот как-то так:
rdtsc
movDWORD PTR _start, eax
movDWORD PTR _start+4, edx
movecx, 1000000
label_loop:
pushf
; nop
popf
loopnzlabel_loop
rdtsc
movDWORD PTR _stop, eax
movDWORD PTR _stop+4, edx
Выходит что пара pushf/popf в среднем занимает 100 тактов. Это очень дохуя. Придётся отказаться от их использования и лепить дополнительные проверки/переходы.
Но всё же интеренсно как поведут эти инструкции на других x86 "камнях".
Ой, а у нас бамплимит уже! Запили, только шапку не проеби.
Это заблуждение из времён 8086.
А вот и перекот. Хуй знает зачем перекатываю и вообще слежу, сам уже ничего не делаю, но тред родной уже.
ПЕРЕКАТ
>>1216107 (OP)
>>1216107 (OP)
>>1216107 (OP)
ПЕРЕКАТ
>>1216107 (OP)
>>1216107 (OP)
>>1216107 (OP)
ПЕРЕКАТ
Для меня сейчас всё потеряло смысл. Хотя наконец-то нашёл работу по профилю уеб-макакой а не полы пидорасить, может, получшает. Да и сам на десятку переехал пару месяцев назад, так что допилка XP теперь только в качестве спортивного интереса, десятку я так и за 1000 лет не отревершу. Надо бы собраться с силами и выложить накоденное.
:3
А если нужно из одной процедуры вызвать вторую, а из второй третью и т.д.? Тут не в регистр нужно записывать, а в стек, чтобы хранить цепочку ссылок, по которым тебе нужно будет возвращаться. Да и вообще, что это за идиотизм, избавляться от call'ов только, чтобы избавиться от call'ов? Если в коде много процедур, он же заебется для каждой прописывать push label, jmp proc, pop ebx и jmp ebx. И это не добавляет "хорткорности", это просто идиотизм. С тем же успехом можно запретить использовать любые числа, кроме двоичных, потому что ХОРТКОООР. Или вот тебе еще идея: избавься от возможности вводить в память строки в кавычках, пусть пишут ASCII-коды символов опять же, в двоичном коде, чтобы уж точно не для тупых казуалов.
Отписался в мертвом треде -_-
Это копия, сохраненная 19 августа 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.