Гайд Продолжение. вбе(партикли)

Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
1)
адрес функции вбе это впринципе да, догадка построенная на во-первых визуальном подтверждении(я на скрине мышкой навел на адрес как видишь по этому адресу находятся байты инструкций а не просто какая-то билиберда) + поставил брейкпоинт на эту функцию(функция которая находится по третьему указателю) и посмотрел что действительно вызывается когда изменяется видимость(ну пошел под вышку вражескую, эта вышка тебя увидела - функция вызвалась) + символ в дилибе есть RegisterNetvarChangeCallback или как его там. и он принимает указатель на функцию параметром. так что среди параметров должен быть указатель на функцию. первый указатель - на строку, второй тоже на строку(там сбоку не видно но там строка вроде "C_DOTA_BaseNPC"), третий - как раз на байты инструкций, а это и есть функция.
2)
это две инструкции
mov rax, qword ptr: [абсолютный 8 байт адрес]//48 a1 <8 bytes>
jmp rax//ff e0
но закодированные в байтах.
mov обычно бывает на 4 байта, то есть относительный адрес(к текущему нужно прибавить относительный адрес чтобы получить абсолютный адрес), но мне его не хватило поэтому юзаю mov на 8 байт абсолютный, конкретно данные байты 48 a1 <8 bytes> и ff e0 нашел гдето в гугле. если ты через LoadLibrary инжектишь то тебе mov на 4 байта хватит(читай выше в этом треде ответ про "PE регион"), я же мануал мапом инжекчу, то есть дллка моя сидит в куче, поэтому от кучи до PE региона в 4 байта не допрыгнуть и поэтому я юзаю 8 байт. чтобы получить байты на 4 байтовый mov rax гугли либо ищи где-нибудь в самой доте, mov встречается на каждом шагу
блин беда с этим дебаггером у меня ничего не срабатывает, вроде на каждую инструкцию по отдельности бп ставил, но это моя проблема, спасибо))
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
блин беда с этим дебаггером у меня ничего не срабатывает, вроде на каждую инструкцию по отдельности бп ставил, но это моя проблема, спасибо))
ты хоть туда ставишь? ставить надо не на функцию со скрина там где 2 строчки, а на функцию на которую я там навел, то есть тебе нужно перейти по 3му указателю(пкм по этой lea инструкции и follow qword in disassembler) и там поставить бп.
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
ты хоть туда ставишь? ставить надо не на функцию со скрина там где 2 строчки, а на функцию на которую я там навел, то есть тебе нужно перейти по 3му указателю(пкм по этой lea инструкции и follow qword in disassembler) и там поставить бп.
а лол внатуре))
 
practice makes perfect
Пользователь
Статус
Оффлайн
Регистрация
16 Мар 2019
Сообщения
90
Реакции[?]
68
Поинты[?]
20K
А чё за байт типа 41: у тебя на скринах?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
А чё за байт типа 41: у тебя на скринах?
было бы классно если бы ты показал где конкретно. если ты просто про двоеточие в x64dbg в байтах инструкции, то наверно это префикс
Пожалуйста, авторизуйтесь для просмотра ссылки.
столбик pf в таблице. там 0x48 это 64 Bit Operand Size, то есть 48: это операции над 8 байтовыми регистрами а 0x41 это Extension of r/m field, base field, or opcode reg field. ну я не думаю что тебе стоит в это так глубоко вникать лол
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
откройте вашу длл в x64dbg и найдите функцию по символу
можно поподробнее как это сделать, в дбг я только скачать символы для модулей нашел, найти по паттерну с иды тоже не получается
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
можно поподробнее как это сделать, в дбг я только скачать символы для модулей нашел, найти по паттерну с иды тоже не получается
предварительно галочку поставь если не стоит, а остальные галочки все сними(потом обратно вернешь если надо)
x64dbg->options->events->Entry breakpoint
x64dbg->file->open->blablabla\src\repos\x64\release\MyDLL.dll, откроется длл, сработает бп на точке входа(dllmain)
заходишь во вкладку Symbols, там выбираешь свою длл в первой таблице, а во второй таблице в строку поиска вбиваешь имя своей функции где у тебя сам хук(TVC_HOOK например у меня), жмякаешь 2 раза по найденной функции. и вот ты нашел свою функцию. теперь смотришь какие регистры у тебя там засираются и не восстанавливаются(а это как правило rcx,rdx,r8,r9, r10/r11/еще какие-нибудь как компилятор сам решит) и потом восстанавливаешь их руками(MASM). но учти что когда ты добавишь восстановление регистров и снова пересоберешь код то компилятор скорее всего уже другие регистры будет юзать)) у меня например щас собрано ваще без засирания r10 и r11 которые я восстанавливаю получается впустую, но если я уберу эту восстановление готов поспорить что он снова их будет засирать. кароче майкрософты тролят.
альтернативно чтобы не париться можешь просто на MASM всю функцию написать.
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
предварительно галочку поставь если не стоит, а остальные галочки все сними(потом обратно вернешь если надо)
x64dbg->options->events->Entry breakpoint
x64dbg->file->open->blablabla\src\repos\x64\release\MyDLL.dll, откроется длл, сработает бп на точке входа(dllmain)
заходишь во вкладку Symbols, там выбираешь свою длл в первой таблице, а во второй таблице в строку поиска вбиваешь имя своей функции где у тебя сам хук(TVC_HOOK например у меня), жмякаешь 2 раза по найденной функции. и вот ты нашел свою функцию. теперь смотришь какие регистры у тебя там засираются и не восстанавливаются(а это как правило rcx,rdx,r8,r9, r10/r11/еще какие-нибудь как компилятор сам решит) и потом восстанавливаешь их руками(MASM). но учти что когда ты добавишь восстановление регистров и снова пересоберешь код то компилятор скорее всего уже другие регистры будет юзать)) у меня например щас собрано ваще без засирания r10 и r11 которые я восстанавливаю получается впустую, но если я уберу эту восстановление готов поспорить что он снова их будет засирать. кароче майкрософты тролят.
альтернативно чтобы не париться можешь просто нMASM всю функцию написать.
сори в ассемблере ноль полный, если писать всю функцию на нем, то можно саму функцию из дебаггера за основу взять и оформить в __declspec(nacked), чтобы зафиксировать регистры которые не восстанавливаются, и твою функцию асм оставить для востановления нужных регистров? и сама проблема засирания состоит в том что нам важны эти данные в какой-то момент или утечка памяти происходит?
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
сори в ассемблере ноль полный, правильно я выделил регистры, где происходит их засирание? и если писать всю функцию на ассемблере, то можно эту из дебаггера за основу взять и оформить в __declspec(nacked), чтобы зафиксировать регистры которые не восстанавливаются, и твою функцию асм оставить для востановления нужных регистров? и сама проблема засирания состоит в том что нам важны эти данные в какой-то момент или утечка памяти происходит?
__declspec(naked) есть только на х86(если мы говорим про visual studio), на x64 masm, там немного другой синтаксис.
проблема засирания в том, что ты помимо своего хука еще и вызываешь оригинал(иначе у тебя сущности просто не будут отрисовываться:D), а оригинал ожидает что в регистрах будут какие-то нужные ему данные. так вот своим хуком ты эти важные для оригинала регистры засираешь, поэтому перед вызовом оригинала надо эти данные восстановить, то есть в своем хуке сначала запихиваешь данные из регистров в оперативку, делаешь свои действия в хуке, а потом из оперативки обратно в регистры данные вываливаешь. на скрине да, правильно выделил регистры, но это не все, там я так понимаю снизу еще код есть. в общем каждую mov и lea прочекай и выпиши себе все регистры в блокнот там куда-нибудь, потом просто на MASM все эти регистры сохрани. у меня там в примере из тутора сохранение rcx,rdx,r8,r9 и r10,r11.
я сначала сую rcx,rdx,r8,r9 в глобальные переменные(хотя можно было бы их в стек просто засунуть, то есть в локальные переменные), потом через masm получаю r10 и r11, сую их в глобал переменные, делаю свои грязные дела(ну чекаю там героев и ставлю им видны они или нет), потом через masm восстанавливаю r10 и r11(код mov r10,rcx; mov r11, rdx; ret; тайпдеф setr1011(u64 rcx, u64 rdx); вызываю setr1011(g_r10,g_r11) ), и восстанавливаю rcx,rdx,r8,r9 через пустую функцию(ну то есть компилятор сам перед вызовом этой пустой функции засовывает все куда надо, поэтому код функции просто ret) типа setFC(g_rcx,g_rdx,g_r8,g_r9).


вот у меня на скрине используются rax, rcx,rdx,r8,r9,rbx,rbp,rsi,rdi. rax можно засирать(я в таком месте хукнул что там rax потом перезаписывается, то есть я могу его засирать спокойно. оригинал функция сама туда засунет что ей нужно), rcx,rdx,r8,r9 я руками восстанавливаю, а rbx,rbp,rsi,rdi компилятор сам восстанавливает. также восстанавливаю r10 и r11 но они не используются(просто если я уберу это восстановление r10 и r11 компилятор пересоберет код и уже будет их юзать, говорю же майкрософты тролят :)). так что почекай все свои регистры которые используются в mov/lea, определи из них те которые сами восстанавливаются(push+pop/mov [rsp+xxx],register + mov register,[rsp+xxx](то есть в стек засовываются потом высовываются)), определи те которые не восстанавливаются(в моем случае rcx,rdx,r8,r9), восстанови их через masm.
 
practice makes perfect
Пользователь
Статус
Оффлайн
Регистрация
16 Мар 2019
Сообщения
90
Реакции[?]
68
Поинты[?]
20K
было бы классно если бы ты показал где конкретно. если ты просто про двоеточие в x64dbg в байтах инструкции, то наверно это префикс
Пожалуйста, авторизуйтесь для просмотра ссылки.
столбик pf в таблице. там 0x48 это 64 Bit Operand Size, то есть 48: это операции над 8 байтовыми регистрами а 0x41 это Extension of r/m field, base field, or opcode reg field. ну я не думаю что тебе стоит в это так глубоко вникать лол
Вот на первом скрине,на инструкции которая у тебя выделена
48:00D
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
Вот на первом скрине,на инструкции которая у тебя выделена
48:00D
48: 8D 0D <4 byte rel> - lea rcx, qword ptr ds:[blablabla]
открываешь ту ссылку которую я скинул и смотришь
первый байт 48(столбик pf, prefix) обозначает 8 байт операнд(qword) (то есть адрес blablabla, а это как раз qword), а не регистр как я напиздел в прошлом ответе
второй байт 8d(столбик po, primary opcode) означает lea
третий байт 0d(ModR/M) означает rip+disp32(ну то есть относительный 4 байт адрес, как я называю 4 byte rel) и регистр rcx

впринципе тебе эту билиберду знать не нужно, за тебя уже дебагер все сделал и вывел тебе на экран человеко-читаемую инструкцию: lea rcx, qword ptr ds:[blablabla]
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
__declspec(naked) есть только на х86(если мы говорим про visual studio), на x64 masm, там немного другой синтаксис.
проблема засирания в том, что ты помимо своего хука еще и вызываешь оригинал(иначе у тебя сущности просто не будут отрисовываться:D), а оригинал ожидает что в регистрах будут какие-то нужные ему данные. так вот своим хуком ты эти важные для оригинала регистры засираешь, поэтому перед вызовом оригинала надо эти данные восстановить, то есть в своем хуке сначала запихиваешь данные из регистров в оперативку, делаешь свои действия в хуке, а потом из оперативки обратно в регистры данные вываливаешь. на скрине да, правильно выделил регистры, но это не все, там я так понимаю снизу еще код есть. в общем каждую mov и lea прочекай и выпиши себе все регистры в блокнот там куда-нибудь, потом просто на MASM все эти регистры сохрани. у меня там в примере из тутора сохранение rcx,rdx,r8,r9 и r10,r11.
я сначала сую rcx,rdx,r8,r9 в глобальные переменные(хотя можно было бы их в стек просто засунуть, то есть в локальные переменные), потом через masm получаю r10 и r11, сую их в глобал переменные, делаю свои грязные дела(ну чекаю там героев и ставлю им видны они или нет), потом через masm восстанавливаю r10 и r11(код mov r10,rcx; mov r11, rdx; ret; тайпдеф setr1011(u64 rcx, u64 rdx); вызываю setr1011(g_r10,g_r11) ), и восстанавливаю rcx,rdx,r8,r9 через пустую функцию(ну то есть компилятор сам перед вызовом этой пустой функции засовывает все куда надо, поэтому код функции просто ret) типа setFC(g_rcx,g_rdx,g_r8,g_r9).


вот у меня на скрине используются rax, rcx,rdx,r8,r9,rbx,rbp,rsi,rdi. rax можно засирать(я в таком месте хукнул что там rax потом перезаписывается, то есть я могу его засирать спокойно. оригинал функция сама туда засунет что ей нужно), rcx,rdx,r8,r9 я руками восстанавливаю, а rbx,rbp,rsi,rdi компилятор сам восстанавливает. также восстанавливаю r10 и r11 но они не используются(просто если я уберу это восстановление r10 и r11 компилятор пересоберет код и уже будет их юзать, говорю же майкрософты тролят :)). так что почекай все свои регистры которые используются в mov/lea, определи из них те которые сами восстанавливаются(push+pop/mov [rsp+xxx],register + mov register,[rsp+xxx](то есть в стек засовываются потом высовываются)), определи те которые не восстанавливаются(в моем случае rcx,rdx,r8,r9), восстанови их через masm.
спасибо, мощь)
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
27 Май 2020
Сообщения
15
Реакции[?]
2
Поинты[?]
0
еще есть framestagenotify, там тоже какие то postupdate чето там можешь чекнуть там на lwss чето есть по этому поводу.
Если кому то тоже понадобится, ну все же не слишком хорошо привязывать логику к фпс, фпс может быть и меньше чем апдейт рейт в теории на слабых пк.
да, framestagenotify больше всего подходит ! Единственное там enum для stage уже другой. Стали другие значения и больше.

точно так же как в линукс версии номер 29 в vmt CSource2Client
Код:
    void *client =  CreateInterface("client.dll", "Source2Client002");
    FrameStageNotify = VM_ADDR(client, 29);
void* hkFrameStageNotify (void *this_frameStageNotify, uint32_t stage)
0 == Пришел пакет

4 == FRAME_NET_UPDATE_START
между 4 и 5 вызывается PreDataUpdate() для каждого entity
5 == FRAME_NET_UPDATE_POSTDATAUPDATE_START
дальше вызывается PostDataUpdate()
6 == FRAME_NET_UPDATE_POSTDATAUPDATE_END
7 == FRAME_NET_UPDATE_END

stage 1 stage 3 и stage 9 за рендер отвечают скорее всего.
НЕ знаю какая за что, но 9 зависит от фпс. Чем выше тем чаще вызывается.


Не сильно важно но напишу,
msg не обязательно для каждого кол-ва аргументов перегружать, достаточно вот так typedef написать.

typedef void (__fastcall *Msg)(const char *format, ...);
Он как printf с переменным кол-вом аргументов работает.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
Не сильно важно но напишу,
msg не обязательно для каждого кол-ва аргументов перегружать, достаточно вот так typedef написать.

typedef void (__fastcall *Msg)(const char *format, ...);
Он как printf с переменным кол-вом аргументов работает.
это старый говнокод))
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
можешь подсказать, как правильно интерпретировать данный код typedef Ptr<u64> AnyPtr, и как бы этот AnyPtr без данной конструкции выглядел.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
можешь подсказать, как правильно интерпретировать данный код typedef Ptr<u64> AnyPtr, и как бы этот AnyPtr без данной конструкции выглядел.
AnyPtr это просто объединение любого указателя(void*, int*, u64*) в простой u64/обратно в указатель. то есть это просто как скобочками фигарить u64 xx = (u64)FindPattern(xxx) только автоматически чтобы скобочки не надо было писать. u64 xx = FindPattern(xxx);//если FindPattern возвращает AnyPtr то автоматически без скобочек кастует в u64
или например Pointer<MyClass> = GetAbsoluteAddress(xxx);
в общем я могу присваивать с любого типа не используя скобочки для каста и также переводить в любой другой тип без скобочек.
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
а как мы понимаем в каких случаях использовать AnyPtr, а в каких ClassPtr? (например ClassPtr panorama, если мы присвоим AnyPtr будет примерно одно и то же?)
 
Последнее редактирование:
Сверху Снизу