-
Постов
2 999 -
Зарегистрирован
-
Победитель дней
129
Тип контента
Профили
Форумы
Загрузки
Блоги
Сообщения, опубликованные MasterGH
-
-
Вариант 1.
Переименовать exe файл, тоже самое должны сделать юзеры.
Вариант 2.
Искать причину ошибки в исходниках. Я помочь не могу, на это времени нет
-
Хочу предложить, чтобы ссылки для скачивания, скрины и коды были доступны только для зарегестрированных пользавателей
Таким образом и пользователей больше будет
Это принуждение. Не очень хороший способ. Я бывал на таких форумах, впечатление они оставляют не лучшее: "мы вам покажем то-то, если вы зарегистрируетесь". А если я не решил ещё регистрироваться, зачем скрывать то, что обычно доступно
-
Кошмар... Этот тутор скаченный вместе с CE с главного сайта? У меня такого не было.
-
Возможно иногда я буду писать о приёмах или кто-то решит написать здесь свой или рассмотреть чужие.
Концепция которую я рассмотрю первой касается реализация динамического списка объектов на Дельфи.
Реализация динамического списка объектов.
Делать мы будем такую штуку,
а затем я напишу где ещё можно применить динамические списки. На рисунке форма программы. Если мы нажимаем на кнопку мышки, то создаётся объект точки и добавляется в список. Действия ниже абсолютно не сложные.
TMyPixel = class(TObject)
FX: Integer;
FY: Integer;
FText: Integer;
constructor Create(X, Y, Num: Integer);
procedure SetPixel;
end;
procedure TMyPixel.SetPixel;
begin
MainForm.Canvas.PolyLine([Point(FX, FY), Point(FX, FY)]);
MainForm.Canvas.TextOut(FX + 1, FY + 1, IntToStr(FText));
end;
procedure TMainForm.SortBtnClick(Sender: TObject);
var i: Integer;
begin
PixList.Sort(PixCompare); // PixList : TList;
with PixList do
for i := 0 to Count - 1 do TMyPixel(Items[i]).FText := i + 1;
end;Заметка.
Мы можем написать свой динамический список.
Принцип крутится вокруг
setlength(имя массива элементов, размер массива)
и
массив[индекс]:= значение
Это принцип необходимо обернуть в класс и добавить методы: добавление/удаление/вставка/поменять местами и т.п. Каждый раз проверять длину массива length(массив) или sizeof(массив) и если необходимо расширять массив или фрагментировать пустоты в нём при удалении элемента внутри массива.
Существует стандартный класс TObject и класс TList. TList может содержать список объектов. В объект можно обвернуть очень многое.
Если вам нужно то ознакомьтесь с описанием этих классов.
Описание TObject
Тип TObject определяет тип базового класса. Он является самым старым прародителем всех классов - каждый класс, в конечном счете, получен из TObject.
Из-за этого, каждый объект унаследовал методы TObject.
Методы TObject относятся к двум категориям - класс и не класс. Когда предустановленно ключевое слово Class, метод можно вызвать и в объекте класса, и в классе непосредственно. Такой статический метод не может обратиться ни к каким полям класса, потому что сам класс не имеет никаких данных, только объекты - имеют данные.
Некоторые ключевые (статические) методы Class:
function ClassName Выдает имя класса как строку
ClassParent Выдает имя родителя класса
ClassInfo Выдает Run Time информацию класса
InstanceSize Размер объекта класса в байтах
NewInstance Создает новый объект класса
Некоторые ключевые методы Object:
Create Создатель пустого объекта
Free Вызывает Destroy для ненулевых объектов
Destroy Высвобождение памяти объекта
AfterConstruction Вызывается после построения
BeforeDestruction Вызывается перед разрушением
Описание TList
Класс TList очень полезный универсальный контейнер списков. Он отличается от массивов, в которых он обеспечивает более богатые функциональные возможности.
В частности объекты TList могут быть отсортированы. Эта сортировка может быть с использованием любых выбранных критериев. Например, список может содержать набор объектов, которые имеют строку и численные поля. Вы можете отсортировать список по строке, по числу, по обоим, с возрастанием или убыванием, как Вы желаете. И пересортировать позже по другим критериям.
Показанный пример кода показывает такую сортировку.
Ключевые свойства и методы упомянуты ниже.
Свойство Capacity
Используется для установления размера (число указателей на объекты) списка. Предварительно установив в разумное значение, можно избежать множественных перераспределений памяти.
Свойство Count
Число элементов (указателей) в списке. Может быть прочитано или записано. Если размер уменьшен в результате изменения значения Count, то удаляются элементы в конце списка.
Свойство Items
Позволяет обращаться к элементам в списке. Например, myList.Items[2] ; возвращает 3-ий элемент в списке. Это свойство, заданное по умолчанию, вышеупомянутое может быть упрощено до myList[2];.
Свойство List
Возвращает элементы в массиве.
Метод Add
Добавляет элемент в конец списока.
Метод Assign
Заменяет список содержанием другого списка.
Метод Clear
Удаляет все элементы списка, устанавливая Count в 0.
Метод Delete
Удаляет элемент из списка по его позиции в списке.
Метод Remove
Удаляет элемент из списка по его объектному указателю.
Метод Exchange
Меняет позиции двух элементов
Метод Move
Перемещает элемент в новую позицию списка.
Метод Insert
Вставляет новый элемент в список в данную позицию.
Метод First
Получает первый элемент в списке.
Метод Last
Получает последний элемент в списке.
Метод Sort
Сортирует список в соответствии с вашими указанными критериями. Сортировка списка проводится внутри TList, но каждая пара элемента сравнивается, вызывая функцию, которую вы указали для этого метода.
Метод IndexOf
Выдает позицию указанного объекта в списке.
Полный код:
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;
type
TMainForm = class(TForm)
ListBtn: TBitBtn;
ClearBtn: TBitBtn;
DelBtn: TBitBtn;
SortBtn: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ListBtnClick(Sender: TObject);
procedure ClearBtnClick(Sender: TObject);
procedure DelBtnClick(Sender: TObject);
procedure SortBtnClick(Sender: TObject);
private
PixList: TList;
PixNum: Integer;
public
{ Public declarations }
end;
TMyPixel = class(TObject)
FX: Integer;
FY: Integer;
FText: Integer;
constructor Create(X, Y, Num: Integer);
procedure SetPixel;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
const PixColor = clRed;
var CurPixel: TMyPixel;
constructor TMyPixel.Create(X, Y, Num: Integer);
begin
inherited Create;
FX := X;
FY := Y;
FText := Num;
SetPixel;
end;
procedure TMyPixel.SetPixel;
begin
MainForm.Canvas.PolyLine([Point(FX, FY), Point(FX, FY)]);
MainForm.Canvas.TextOut(FX + 1, FY + 1, IntToStr(FText));
end;
function PixCompare(Item1, Item2: Pointer): Integer;
var Pix1, Pix2: TMyPixel;
begin
Pix1 := Item1;
Pix2 := Item2;
Result := Pix1.FX - Pix2.FX;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
PixList := TList.Create;
PixNum := 1; {Счетчик точек}
Canvas.Pen.Color := PixColor; {Цвет точки}
Canvas.Pen.Width := 3; {Размер точки}
Canvas.Brush.Color := Color; {Цвет фора текста равен цвету формы}
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
PixList.Free;
end;
procedure TMainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
PixList.Add(TMyPixel.Create(X, Y, PixNum));
Inc(PixNum);
end;
procedure TMainForm.ListBtnClick(Sender: TObject);
var i: Integer;
begin
with PixList do
for i := 0 to Count - 1 do
begin
CurPixel := Items[i];
CurPixel.SetPixel;
end;
end;
procedure TMainForm.ClearBtnClick(Sender: TObject);
begin
Canvas.FillRect(Rect(0, 0, Width, Height));
end;
procedure TMainForm.DelBtnClick(Sender: TObject);
begin
PixList.Clear;
PixNum := 1;
end;
procedure TMainForm.SortBtnClick(Sender: TObject);
var i: Integer;
begin
PixList.Sort(PixCompare);
with PixList do
for i := 0 to Count - 1 do TMyPixel(Items[i]).FText := i + 1;
end;
end.unit uMain;
Скачать исходники: ссылка
Теперь поговорим что даст список объектов.
Первое - это удобно. Вам не нужно создавать свои классы.
Второе - каждый объект в списке может иметь дочерний объект или родительский. Если один объект разрушается, можно задать разрушение всех дочерних. Вы можете составить список объектов сложной иерархии и через цикл обрабатывать их действия между собой. Можно сказать что я подразумеваю прототип игровых объектов. Они могут толкаться между собой, драться, разрушать делать что-то по определённому алгоритму, получать внешнее воздействие и возможно даже ограниченно приспосабливаться под это воздействие.
-
Давно у нас не было статей и вот пришло время поучаствовать с автором во обмане игры. Статью я откопал случайно, она 2002 года, она покажет как искать цепочку указателей.
Есть некоторые моменты касательно реверсинга. Например, как и когда и какие бряки нужно ставить применительно к СофтАйс. Тоже самое можно сделать и в OllyDbg. Главное понять технику.
Указатель будет вот такого вида:
@(@(@(@(@(@(@(@(862360)+4)+4)+10074))+0C2*4)+4)+A8)
надеюсь без труда вы сможете это представить скобками как мы делаем:
[[[[[[[[862360]+4]+4]+10074]]+0C2*4]+4]+A8] = здоровью (8 пар скобок!)
Статья на мой взгляд написана "кусками", но кое-что понять можно. Для тех кто с СофтАйсом не работал, то выражение к примеру
mov eax,[eax][esi]*4
эквивалентно для OllyDbg:
mov eax,[eax+esi*4]
Итак статья.
Автор: FreeExec
Выбирать особо было не из чего, т.к. на машине стояла только одна игра Newer Winter Nigths. И решено было писать тренер к ней.
Продолжение статьи...
Трейнер это программа, которая позволяет изменять значения в игре, например жизни. Сам я читеров не люблю и втихомолку сильно бью *(. Но так я думал до поры до времени, пока не припёрло к стенке, т.е. к монстру. И набросал я быстренько (ну это как посмотреть) свой трейнер.
С помощью ArtMoney я нашел тот блок памяти, в котором хранятся очки жизни. Было бы всё просто, если бы не одно НО: при каждой новой загрузке это место меняется, это происходит по тому, что программа выделяет память динамически и раз на раз не приходится. Ну, раз программа находит нужное место то и я его смогу найти.)
Примечание: ArtMoney найдёт не одно значение, у меня их было 10. Меняйте эти значения и смотрите за остальными, некоторые ячейки тоже поменяют своё значение на введённое вами. Та ячейка, которая изменяет собой больше ячеек и есть искомая.
Запускаем SoftICE, и ставил брейкпоинт (в дальнейшем БР) на доступ к памяти в ячейку, которую мы нашли. (У меня по адресу 10AEFC70, поэту команда для SoftICE'а выглядит так: bpmd 10AEFC70. Но обратите внимание что под окном кода должно быть написано, что вы в модуле nwmain.text, иначе у вас не чего не выйдет). Жмём F5, когда выскочит SoftICE.
Это должна быть инструкция по адресу 607C87 MOV AX, [ECX+A8]. Т.е. какое-то значение (ECX)+А8 ссылается на жизнь. Следующим шагом нужно отыскать то место где регистр ECX получает своё значение. Чуть ниже этой инструкции стоит команда RET- это выход из функции. Выполняем пошагово (F8) пока не выйдем из функции, и не уведем следующее:
5D05E3 call [edx+00000009C]5D05E1 mov ecx, esi
Ставим БР по адресу 5D05E1 командой "bpx 5D05E1" или двойным щелчком на строке и нажимаем F5 несколько раз, пока ESI не будет равен найденному значению минус A8 (10AEFC70-A8=10AEFBC8). Двигаем код в окне вверх (CTRL+вверх), ища, где ESI получает своё значение, должны дойти вот досюда:
005D0073 call [edx+00030]
005D0076 mov esi,eax005D0071 mov ecx,ebx
Значит, функция возвращает в регистре EAX наше число, но не стоит сразу ковырять внутренности функции, поставив БР по адресу 005D0071, мы увидим, что EBX=10AEFBC8. Чуть выше видим:
005D0049 mov ebx,[esp+00050]
Снова ставим БР на участок памяти ESP+50 "bpmb esp+20 w"(w означает, что отслеживать только запись по этому адресу). Наберём в командной строке "? ESP+50" чтобы получить точный адрес, затем "d ESp+50" чтобы видеть этот участок. Жмём F5 столько раз, пока на этом участке не появится наше значение в перевёрнутом виде, т.е. C8FBAE10 (руки бы оторвать тому, кто это придумал
. Как дальше разворачивались дела я не помню, но вы должны выйти на:
CALL 005CF000 (например, по адресу 5D8D6A, 5D8866)
После выполнения этой функции EAX содержит наше число. Значит способ получения этого числа в этой функции. Вот содержимое этой функции (примечание: все числа после точки с запетой приведены конкретно для моего примера, у вас они могут быть другие):
mov eax,ecx
mov ecx,[000862360] ; ECX=A6BA590 (7)
mov edx,[eax][00030]
mov ecx,[ecx][00004] ; ECX=[A6BA594]=79A6058 (6)
push edx
call .0005BB7E0
5BB7E0:
mov eax,[esp][00004]
mov ecx,[ecx][00004] ; ECX=[79A605C]=7A58008 (5)
push eax
call .0005C2B10
5C2B10:
push ecx
mov edx,[esp][00008]
mov ecx,[ecx][000010074] ; ECX=[7A6807C]=79F1CB8 (4)
lea eax,[esp][00000]
push eax
push edx
mov d,[esp][00008],000000000
call .0004259D0
4259D0:
mov eax,[esp][00004] ; EAX=20C2
push esi
mov esi,eax
shr esi,01F ; ESI=0
and esi,001
mov edx,eax
and eax,000000FFF ; EAX=0C2
shl esi,00C ; ESI=0
add esi,eax ; ESI=0C2
mov eax,[ecx] ; EAX=[79F1CB8]=7A1EFF8 (3)
mov eax,[eax][esi]*4 ; EAX=[7A1F300]=7BD1E08 (2)
and edx,07FFFFFFF
test eax,eax
pop esi
je .000425A04
cmp [eax],edx
je .000425A13
mov eax,[eax][00008]
test eax,eax
jne .0004259F9
mov ecx,[esp][00008]
mov d,[ecx],000000000
mov al,001
retn 00008
mov edx,[eax][00004] ; EDX=10AEFBC8 (1)5CF000:
Цифрами в скобках обозначены ключевые моменты кода. Мы видим, чтобы получить нужный адрес надо прочитать DWORD по адресу EAX+4. В свою очередь этот EAX=EAX+ESI*4, где ESI=0C2. И так далее. Чтобы проверить правильность наших рассуждений пишем в командной строке SoftICE'а "? @(10AEFBC8+A8)", программа должна написать текущее количество жизни (первое число в шестнадцатеричное, а вот второе десятичное). Теперь надо заменить число 10AEFBC8 на то, что мы получили, т.е. на @(7BD1E08+4). Соединяем все вместе - должно получится "? @(@(7BD1E08+4)+A8)". Аналогичным способом движемся выше до строки обозначенной (7), там адрес задан конкретно. Он будет всегда один и тем же. В итоге у меня получилось так: "? @(@(@(@(@(@(@(@(862360)+4)+4)+10074))+0C2*4)+4)+A8)". Вот в принципе и всё что касается нахождения нашей жизни
Можно уже юзать это совместно с SoftICE'ом.
Но я пошёл дальше и написал трейнер. Здесь я не буду приводить полный исходник, его вы можете взять здесь, а приведу лишь ключевые моменты программы, дабы не навязывать какой либо язык программирования.
Чтобы иметь возможность изменять данные в чужом процессе (программе) нужно знать её идентификатор процесса. Его можно получить используя функцию NtQuerySystemInformation(5, адрес_буфера, размер_буфера, 0), из библиотеки ntdll.dll. Чем больше процессов запущено, тем больше нужен буфер. У меня он составляет 7 Кб. Буфер состоит из массива структур ProcessInfo. По 0 смещению задан размер структуры DWORD. А со смещением 3C ссылка на имя процесса в формате UniCODE. По смещению 44 находится идентификатор процесса. Затем открываем этот процесс функцией OpenProcess(1F0FFF,0,идентификатор_процесса), она возвратит нам хендл на этот процесс. С помощью функции ReadProcessMemory(Handle, адресс_в_процессе_ откуда_читать, адресс_буфера_ куда_записать, сколько_прочитать, 0) сначала читаем по адресу 862360, прибавляем к этому значению 4 и снова читаем по полученному адресу, и т.д. Запись в память производится с помощью WriteProcessMemory(Handle, адрес_куда_записывать, адрес_буфера, сколько_записать, 0).
Процесса заморозки можно добиться, используя вызов по таймеру. Создаём таймер - SetTimer(hWnd-идентификатор_окна, уникальный_номер, время_в_милисек, 0 или адрес_процедуры_ которая_будет_вызываться). Если последний аргумент равен 0, то процедуре обработки окна будет приходить сообщение WM_TIMER, если таймеров много то отличить их можно по уникальному номеру, который был задан при создании таймера, он находится в переменной wParam. Не забудьте удалить таймер при выходе KillTimer(hWnd, handle).
Ну, вот в принципе и всё, осталось нарисовать морду будущей проги и описать несколько функций.
P.S. Функция NtQuerySystemInformation доступна только NT системам в Win9x нужно юзать CreateToolhelp32Snapshot, Process32First, Process32Next чтобы получить идентификатор нужного процесса.
-
По поводу первого, я хоть и вхожу в группу администраторов, но в форумских движках не копался да некогда разбираться, к сожалению.
По поводу второго это не удобно. Удерживай Shift и переходи по ссылкам. Ещё вариант - средняя кнопка мышки.
-
....
4. Должно помочь, если не помогло, то переустанови другую версию Икс Пи
Не разобравшись в проблеме переустанавливать Дельфи, а также операционку не стоит. Возможно, проще начать разобираться с кодировками в настройках Дельфи, а затем разбираться с кодировкой в ОС-ме в связке с кодировкой в Дельфи. Подходят ли кодировки, почему не подходят?! Кому сильно докучает эта проблема, могу попробовать поискать решение проблемы. Переустанавливать Дельфи и тем более ОС не стоит. Попробую ещё раз без лени решить эту проблему, если решу, то отпишусь....
Посмотрел я. У меня этой проблемы нет почему-то. Сама как-то отпала )
-
1. Впорос. По нажатию мышки на элементе полученного с сервера его данные, т.е. целая строка должна передаться в поле ввода. Перечитал туторы не очень понимаю, как это сделать.
Я эту задачу решил и позже дам ответ.
А вторую задачу ещё можно обсудить =)
PS Советую любителя javascript зайти на сайт и узнать инфу по работе с событиямисайт =)
-
Спасибо SER[G]ANT.
Кстати чтобы тебя цитировать приходиться убирать скобки SER[G]ANT
Так тоже можно (?)
var
x,y: Integer;
begin
for y := 0 to Form1.Height
do for x := 0 to Form1.Width
do if (y mod 5 = 0) and (x mod 5 = 0)
then Form1.Canvas.Pixels[x,y] := clBlack;
end;procedure TForm1.FormPaint(Sender: TObject);
Form1.Height и Form1.Width это не клиентская область поэтому будут некоторые смещения у сетки.
Когда в цикле делаешь do for x := 0 to Form1.Width, то возможно (я точно не помню) это будет сказываться на производительности, т.к. каждый раз будет расчитываться путь до значения "with" через смещение от "Form1." Этот цикл сравнения if (y mod 5 = 0) and (x mod 5 = 0), тоже влияется на производительность. Но я только предполагаю, надо лесть в отлдаку и сравнивать производительность.
-
Лучше бы привёл решение. Мне интересно было бы глянуть.
Да и пользы будет больше: нашёл тему и нашёл ответ, а не узнал что кто-то нашёл ответ.
-
Вводим в поле слово и похожие слова динамически подгружаются с IIS сервера по запросу который я составил
<asp:AccessDataSource ID="AccessDataSource1" runat="server"
DataFile="~/App_Data/test.mdb"
SelectCommand="SELECT [fsText] FROM [tblRecords] WHERE ([fsText] LIKE ? + '%')"
onselecting="AccessDataSource1_Selecting">
<SelectParameters>
<asp:Parameter Name="fsText" Type="String" />
</SelectParameters>
</asp:AccessDataSource>1. Впорос. По нажатию мышки на элементе полученного с сервера его данные, т.е. целая строка должна передаться в поле ввода. Перечитал туторы не очень понимаю, как это сделать.
<input id="Text1" type="text" onkeyup="Send()"/></div>
<table class="Table">
<tr><td onclick="ClickTD(this)"><span class='FontSearch'>Животное1</span> на крыше</td></tr>
<tr><td onclick="ClickTD(this)"><span class='FontSearch'>Животное2</span> на крыше</td></tr>
</table>Вызываем функцию ClickTD(this)
function ClickTD(e) {
v = e.toString();
document.getElementById("Text1").value=v;
}В общем идёт не значение поля которое вызывало функцию, а что-то другое. Есть у гугла такая штука тоже, но я не разобрался.
2. Впорос. Сетевой трафик.
Умные люди пишут, что всячески нужно стараться снимать нагрузку с машины сервера и уменьшать трафик обмена. Если посмотреть на рисунок сверху, то видно что получение данных может быть двумя способами.
1) Вот эта разметка полностью строиться на сервере и динамически (без перезагрузки всей страницы) передаётся клиенту
<input id="Text1" type="text" onkeyup="Send()"/></div>
<table class="Table">
<tr><td onclick="ClickTD(this)"><span class='FontSearch'>Животное1</span> на крыше</td></tr>
<tr><td onclick="ClickTD(this)"><span class='FontSearch'>Животное2</span> на крыше</td></tr>
</table>где каждое животное берём из базы.
2) Способ не формировать эту разметку на сервере, а скинуть не форматированные данные...
Животное1@
Животное2@...клиенту в функцию, которая построит всю разметку и динамически встроит её в тег div-а (pop-up) панели.
Первый способ очень простой на C# и удобен и гораздо лучше соблюдается интеграция в другие проекты с приминением ООП C#. Также код формирования разметки закрыт от сторонних глаз. В этом случае те кто захотят такое же формирование разметки им придётся самим писать код или обращаться на мой сервер чтобы получить разметку снова.
Итак плюсы первого способа: интеграция ООП, закрытый код.
Минусы: увеличение нагрузки на сервер и увеличение трафика, клиенту дольше ждать ответа с сервера вместо того чтобы самому обработать скрипт.
Про второй способ, когда разметка формируется на клиенте.
Плюсы для меня: меньшая нагрузка на сервер, меньше трафика.
Минусы: код javascript менее удобен как в написании так и в интеграции с будущеми поектами на ООП C#.
С этим разумный вопрос не ужели нужно учитывать все плюсы и минусы двух способов или нужно придерживаться жёстко второго способа. Короче что выбрать и как?
-
Можно взять такой вариант.
unit _Paint;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
limitX: integer;
limitY: integer;
_Canvas: TCanvas;
_Color: TColor;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
limitX:=10;
limitY:=10;
_Canvas:=Form2.Canvas;
_Color:=0;
end;
procedure TForm2.FormPaint(Sender: TObject);
var
aWidth: integer;
aHeigth: integer;
i,j:integer;
begin
aWidth:=Form2.ClientWidth div limitX;
aHeigth:=Form2.ClientHeight div limitY;
for i:=0 to aWidth do
for j:=0 to aHeigth do
_Canvas.Pixels[i*limitX,j*limitY]:=_color;
end;
end.Правда есть и более производительный вариант с так называемой "подложкой" - картинокой. Подложка должна рисоваться внутри TForm2.FormPaint на самой Form2а изменяться внутри TForm2.OnResize.
-
У нас появился закрытый раздел "Наши разработки". Делается это для того чтобы нашими исходными кодами не пользовались без спросу или хотя бы ограничить это пользование.
В этот раздел можно входить под паролем или без пароля для группы пользователей "Разработчики". Этот статус очень почётный.
В этой теме будут различные новости и информация о ходе совместных работ по разработке программ связанных с гейм хакингом. В частности это ТрейнерМакс(Delphi), Движок-Автоматических Иньекций(Delphi), Исследовательский движок дизассемблированного текста для встраивания в наш форум (Javascript). Последний нам позволит обмениваться опытом или подсказывать друг другу выходы из различных ситуаций и совместно анализировать тот или иной код.
Участники могут помогать в изменении кода проектов, исправлении ошибок, создание своего кода с заданной задачей или предложить ту или иную свою идею.
Те кто принял участие в модернизации CE автоматически войдут в группу Разработчиков. Остальные желающие получить доступ в скрытый раздел могут написать администрации личное сообщение. Тем кто учится программировать, тоже рекомендуется вступить в группу и влиться в общую деятельность по мере того как вам будет позволять время и желание.
-
1
-
-
У меня бывала такая ситуация, когда с английской раскладкой копируешь в буфер обмена исходный код в котором русские комментарии. В этом случае нужно изменить раскладку перед копированием. С другими случаями не сталкивался.
В других случаях глянь настройку шрифтов Дельфи.
-
Наброски что-то типа этого, но должны быть варианты и по эффективнее:
newmem:
push eax
mov eax,[pPlayer]
mov eax,[eax+14]
mov eax,[eax+30] //для игрока eax=x, eax+4=y, eax+8=z
push ebx
push ecx
mov ebx,[LocateCoord]
mov ecx,[IndexLoc]
lea ebx,[ebx+ecx]//[LocateCoord]+[IndexLoc]=X
mov ecx,[ebx]
mov [eax],ecx
mov ecx,[ebx+4]
mov [eax+4],ecx
mov ecx,[ebx+8]
mov [eax+8],ecx
pop ecx
pop ebx
pop eax
dd pPlayer
dd pPlayerCoord
dd LocateCoord
dd IndexLoc-
1
-
-
А зачем вообще делать фильтр, если есть рабочая цепочка указателей? В любую частовыполняемую инструкцию достаточно вставить запись нужного здоровья по этой цепочке и все.
Ну так требуется one hit kill
Делается в инструкции типа: B, C(B ). Без фильтра никак.
Хотя есть вариант при one hit kill, чтобы не писать фильтр (как я мог не предвидеть раньше). Надо найти инструкцию типа A для здоровья врагов, обращение к которой происходит при стрельбе в них. Тогда фильтра действительного писать не нужно.
-
Я не разбирал - пока некогда.
Разбираться стоит с самого начала. Когда включаем этот режим в настройках, то должен учитываться флаг этого режима. А дальше через поиск по всем исходникам в среде Дельфи можно найти все условности связанные с этим флагом. В данном случае связанные с автоассемлированием и вообще записью в память и чтения из неё.
-
1. Найти/проверить инструкцию типа А.
Предпологаемая инструкция (по вашим данным):
game.exe+231B0D - fld dword ptr [eax+08]
Поставить определение адресов на этой инструкции. Если на ней проскакивают адреса врагов значит это тип не А.
Поставить бряк на адресе здоровья врага, получить инструкции (в частности при стрельбе во врага...)
Сравнить инструкции при бряке на адресе здоровья своего героя с инструкциями при бряке на адресе врага и найти инстуркцию типа А.
Если не нашли типа А, то идём вверх по указателю на один уровень и точно также ищем тип А ставив бряк на указатели своего героя и врага.
Если не нашли, то опять идём вверх уже на конечный третий уровень пока не найдём тип А.
На последнем уровне точно должна быть типа А.
2. После нахождения инструкции типа А, нужно её изменить инъекцией чтобы
сохранить указатель на некоторый уровень.
[[[{3ий уровень}адрес+смещение]{2ой уровень}+смещение]{1ый уровень}+смещение] // {комментарии}
Допустим "вынесли" (т.е. сохранили для фильтра) указатель с третьего уровня.
3. В инструкции работающей непосредственно со здоровьем, т.е с 1-ым уровнем нужно сделать инъекцию кода,
так чтобы 3-тий уровень был в качестве фильтра.
Фильтр например напишем так
"Если [[{3ий уровень}адрес+смещение]{2ой уровень}+смещение] = 1ый уровень, то записать здоровье своему игроку."
Это самый простой способ, но с новыми патчами может оказаться не рабочим.
Примечение.
Для увелечения работоспособности:
- поиск адреса внедрения через проверочные байты;
- (CE на сегодняшний момент этого делать не умеет через так называемое автодизассемблирование)
идентификация смещений в уровнях цепи указателей перед автоассемблированием,
идентификация перед автоассемблированием регистров левой и правой частей инструкции по адресу внедрения, т.е. операндов источника и адресата. И конечный реультат - автоассемблирование с сгенериованным скриптом по указанным правилам: писать здоровье своему игроку и OneHitKill.
-
Сделать полную сохранялку конкретной или любой игры дело не простое.
Как минимум требует многочасовой работы и экспериментов.
Но есть несколько возможных альтернативных вариантов.
1. Использовать эмулятор Windows.
2. Поискать программу в интернете.
3. Поговорить с разработчиками Артмани, которые за это дело требуют деньги.
4. Написать Дарк Байту (автору CheatEngine). Написать ЭльСпиро (разработчику MHS).
Ещё есть разработчики WGC,DS - но они врядли этим будут заниматься.
5. Попробовать каким-то изворотливым способом через Artmoney, экспериментируюя отключая звук, замораживая или удаляя какие-то потоки процесса через системыне утилиты.
-
Может пуля за раз отнимает все жизни, но это врядли. Скорее всего где-то есть либо ещё одна структура повреждений, либо флаг смерти какой-то.
Почему приведённый скрипт защищает от воды, но не защищает от пуль?
А главное - почему при включении спидхака скрипт и от воды перестаёт защищать? Обновлять значения не успевает чтоли..
Возможные причины не работающего бессметрия:
1. Не найден адрес здоровья или найдены не все (что скорее всего).
Проверить это можно, ставив бряк на запись на адреса здоровья своего героя и на адреса здоровья других игроков.
2. Адрес (или адреса) здоровья может находиться в структуре1. С неё снимается копия в структуру2 и код который работает с этой структурой может повлиять на смерть героя.
Больше вариантов у меня нет, если не тратить время чтобы придумывать их. Как написал Xipho необходимо смотреть в отладке. Хорошо бы найти несколько структур и постарать найти адреса-зацепки которые изменяются во время смерти некотрого игрока, но не своего...
У меня пока только одна идея - в игре есть редактор миссий (в демке его нет), в этом редакторе есть скриптовая команда setdammage. Если бы придумать как вызвать эту команду во время игры, без редактора, можно было бы сделать бессмертие. Но как её вызвать я не понял(( либо искать причину гибели от пуль в другом месте
Если setdammage работает в редакторе, то надо проследить в какую функцию идёт эта комманда. Попытаться найти её в самой игре. Я думаю, проще искать причину гибели от пуль.
Это делать надо в Olly и брякнуться в момент оповещения о сметри героя. Именно брякнуться. Запомнить это место - Бряк1. Посмотреть стек вызовов и на каждом вызове поставить бряки. Перезапустить игру и играть если прерываемся и очевидной смерти нет, то снимаем бряки кроме 1. Если остался бряк1, то надо чё-то думать.
И наконец когда смерть вновь произошла и сработал один из бряков, то плясать уже на этом уровне кода и смотреть что там происходит.... В общем не знаю как объяснить и предположить иное.
-
А разве второй и третий баг из первого поста Сержант не исправил?
del
Попозже разберусь.
-
Хорошая статья по игре Bloodrayne 2 Demo.
Но можно сделать ещё лучше - свою статью на основе этой с некоторыми скринами ключевых моментов на CheatEngine на той же самой игре Bloodrayne 2 Demo. Конечно это тебе решать
-
В разработке Периодически этот действующий список буду пополнять,а когда функций накопится, то выложу.
Cheat Engine 5.6 RUS (2.0)
Добавления:
1. Более удобная работа со скриптами в таблице CE: можно редактировать несколько скриптов подряд и корректно сохранять
2. В автоасемблере можно вводить имя будущего скрипта или исправлять имя редактируемого скрипта (помог SERGANT)
3. Звуковые уведомления:
-Звук при завершении сканирования
-Звук при нажатии на хоткей относительно таблицы CE
-Звук при нажатии на хоткей отностильено созданного трейнера
-Можно поменять файлы звукового оповещения ("Удачное событие", "Ошибка")
4. Некоторые добавления:
-"numeric" тебперь обозначаются как "NUMPAD"(помог SERGANT)
- Добавлено контекстное меню в кнопку "Т"(SERGANT)
- Изменён интерфейс "Создателя трейнера"(SERGANT)
Баги:
1. Работает поиск значений после поиска указателей. (SERGANT)
2. После сброски настроек CE (удаления ветки реестра) при помощи ceregreset.exe, больше не предлагает запустить Tutorial.exe (будет предлагать если только вы запустили CE первый раз или на чистой системе)
3. Исправлен баг в русской версии, при котором невозможно было выделить найденный адрес(SERGANT)
4. Исправлен баг, который заемучил всех пользователей Vista/7 с темой Aero, а именно, при нажатии клавиши "Alt" исчезали компоненты (кнопки, текст, чекбоксы и т.д.). Данный баг не CE, а Delphi программ в целом.(SERGANT)
5. Открытие окон создания трейнера при переходе по адресу в область памяти.
6. Корректное удаление регистарции хот-кеев при их активации (наткнулся на этот баг когда звук нажатия хоткея повторялся после удаления этого хоткея)
-
Статус: баг исправлен
Корректное удаление регистрации хот-кеев при их активации (наткнулся на этот баг когда звук нажатия хоткея повторялся после удаления этого хоткея)
Исправление:
-модуль HotkeyHandler:
-строка:251
Было:
setlength(hotkeythread.hotkeylist,length(hotkeythread.hotkeylist)-1);
Изменил:
setlength(hotkeythread.hotkeylist,length(hotkeythread.hotkeylist)-2);
[sp=После первого удаления хоткея hotkeythread.hotkeylist был](((0, 0, 0, 0, 0), 5441632, 0, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 1, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 2, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 3, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 4, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 5, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 6, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 7, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 8, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 9, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 11, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 12, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 13, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 14, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 15, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 16, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 17, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 18, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 19, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 20, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 21, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 22, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 23, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 24, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 25, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 26, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 27, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 28, 0, 0, True, 0),
((0, 0, 0, 0, 0), 5441632, 29, 0, 0, True, 0),
((81, 0, 0, 0, 0), 5441632, 10, 0, 81, False, 0) // не очищалось поэтому надо скосить низ иначе при удалении хот-кея, он все равно остётся "живым" и информация о нём "наслаивается")[/sp]
Взлом объектных типов
in Статьи для продвинутых
Опубликовано
Сегодня наткнулся на полезное описание функции __RTDynamicCast похожее на _RTDynamicCast. И её и другие функции я размещу ниже.
В игре Sniper: Ghost Warrior
из информации сохранения конструктор создаёт в объекте игрока массив (указателей 30 подобъектов и 30-ти типов) из них не более 8-ми могут быть гранаты.
Массив типа {{DWORD,VOID *}, ...}
Первый например 0x14 (это ID типа гранат)
Второй например 16A324D8 (это указатель на объект гранаты)
В конструкторе есть функция _RTDynamicCast привидения любого из 30 классов сохранённых объектов к игровым объектам.
_RTDynamicCast(v21, 0, &off_10A14088, &off_10A19214, 0);
где
первый парметр указатель на объект, который приводим к базовому классу
второй параметр обычно ставят ноль, не помню что это
[off_10A14088] = "AVISaveGame";
[off_10A19214] = "AVInvObject";
Последний ноль - генерировать ли исключение при ошибочном привиденияя
Описание на англ.
* PARAMS
* cppobj [] Any C++ object to cast
* unknown [] Reserved, set to 0
* src [] type_info object describing cppobj
* dst [] type_info object describing the base class to cast to
* do_throw [] TRUE = throw an exception if the cast fails, FALSE = don't
Рассмотрим часть кода:
Полный код можно посмотреть здесь