Jak napisać własne macro do Tibii
« Powrót do listy Artykułów
<a href="http://www.game-advertising-online.com/" target=_blank>Game Advertising Online</a><br> banner requires iframes
Autor: Yaboomaster Data: 15.08.2007
Ocena: 5 >>Komentarze (224)<<
Witam ;)

Jestem Yaboomaster twórca bota do Tibii Yaboobot. Pewnie nie jeden z was chciał by mieć swojego własnego bocika :P Kiedyś też zaczynałem od zera i pomógł mi właśnie taki poradniczek :P

Od czego zacząć? Warto zacząć od wybrania języka programowania :P Ja wybrałem Delphi i właśnie o ten język oprę ten poradnik. (Killavus twierdzi że Delphi to shit‚ więc niech sobie dalej ogląda filmy 18+ xd).

Jako że na forum coś się zmieniło i nie wyświetla się znaczek "małpa" (shift+2) a zamist niego pokazuje się # powinniście uwzględnić to w waszych projektach zamieniając to na "małpę"

Source

1. Przygotowanie Projektu

Odpalamy Delphi (ja używam wersji 7 personal)
File > New > Application
w
Przed nami pojawi się Form1 i Unit1
Teraz dajemy File > Save as > wybieramy miejsce i zapisujemy jako BOT
Teraz File > Save project as > wybieramy miejsce i zapisujemy jako Tibia_bot(albo jakoś inaczej).

2. Pierwsze Kroki

Jeżeli mamy już zapisany projekt możemy przystąpić do pisania pierwszych funkcji. Będą to funkcje odczytywania i zapisywania danych z pamięci klienta Tibii.
Może to trochę dziwnie brzmi ale już tłumaczę :)

Klient Tibii (tibia.exe) przechowuje w sobie różne dane (hp‚ mana‚ nick i wiele wiele innych) za pomocą funkcji "Readprocessmemory" możemy te dane odczytywać. "WriteProcessMemory" dzięki tej funkcji możemy je tam zapisywać.
Zastosowanie (teoria)
Odczytywanie wartości typu hp mana itp - Readprocessmemory
Zapisywanie wartości (zmiana nicku itp) - WriteProcessMemory

Ale dane są zapisane w różny sposób‚ nick to string‚ hp integer itp. Żeby odczytać te dane trzeba napisać 2 różne funkcje.

Odczytanie tekstu (string)

[CODE]function MemReadString(Address: Integer): String;
var
NB : LongWord;
Temp : ARRAY [1..255] OF Byte;
I : Byte;
IDProcess‚ proc_ID : Cardinal;
begin
GetWindowThreadProcessID(FindWindow('TibiaClient'‚ nil)‚ @proc_ID);
IDProcess := OpenProcess(PROCESS_ALL_ACCESS‚ false‚ proc_ID);
Result := '';
ReadProcessMemory(IDProcess‚ Ptr(Address)‚ @Temp[1]‚ 255‚ NB);
for I := 1 to 255 do
begin
if ((Temp[I] = 0) or (Temp[I] = $0F)) then
Break;
Result := Result + Chr(Temp[I]);
end;
end;[/CODE]

Odczytanie liczb (integer)

[CODE]function ReadMemInteger(Address: Cardinal): Cardinal; //Read adress:value
var
ProcId: Cardinal;
tProc: THandle;
NBR: Cardinal;
value:integer;
begin
GetWindowThreadProcessId(FindWindow('TibiaClient'‚Nil)‚ @ProcId);
tProc:= OpenProcess(PROCESS_ALL_ACCESS‚ False‚ ProcId);
ReadProcessMemory(tProc‚ Ptr(Address)‚ @value‚ 4‚ NBR);
CloseHandle(tProc);
Result:=value;
end;[/CODE]

Już objaśniam ich działanie

[CODE]
function function ReadMemInteger(Address: Cardinal): Cardinal;
[/CODE]

Address - wartości w kliencie Tibii mają swoje miejsca(czyt. Adresy). Adresy te wyglądają np tak "60EAC0" (w tym miejscu zapisany jest level twojej postaci).

Żeby odczytać level postaci wystarczy więc użyć funkcji ReadMemInteger(Level_Postaci);

Gdzie Level_Postaci to ten adres 60EAC0;

3. Odczytujemy Dane

Podane wyżej funkcje należy wstawić pod napisem "implementation" (będzie już domyślnie ustawiony).

Jeżeli robiłeś wszystko zgodnie z instrukcją powinieneś otrzymać coś takiego

[CODE]unit Bot;

interface

uses
Windows‚ Messages‚ SysUtils‚ Variants‚ Classes‚ Graphics‚ Controls‚ Forms‚
Dialogs;

type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
// Funkcje czytające

function ReadMemInteger(Address: Cardinal): Cardinal; //Read adress:value
var
ProcId: Cardinal;
tProc: THandle;
NBR: Cardinal;
value:integer;
begin
GetWindowThreadProcessId(FindWindow('TibiaClient'‚Nil)‚ @ProcId);
tProc:= OpenProcess(PROCESS_ALL_ACCESS‚ False‚ ProcId);
ReadProcessMemory(tProc‚ Ptr(Address)‚ @value‚ 4‚ NBR);
CloseHandle(tProc);
Result:=value;
end;


function MemReadString(Address: Integer): String;
var
NB : LongWord;
Temp : ARRAY [1..255] OF Byte;
I : Byte;
IDProcess‚ proc_ID : Cardinal;
begin
GetWindowThreadProcessID(FindWindow('TibiaClient'‚ nil)‚ @proc_ID);
IDProcess := OpenProcess(PROCESS_ALL_ACCESS‚ false‚ proc_ID);
Result := '';
ReadProcessMemory(IDProcess‚ Ptr(Address)‚ @Temp[1]‚ 255‚ NB);
for I := 1 to 255 do
begin
if ((Temp[I] = 0) or (Temp[I] = $0F)) then
Break;
Result := Result + Chr(Temp[I]);
end;
end;
// Koniec - Funkcje czytające

end.[/CODE]

Teraz naciśnij Ctrl+F9 (projekt zostanie skompilowany) możesz go uruchomić wciskając F9

Na razie będzie on wyglądał tak (możecie zmniejszyć okno bota po prostu wydłużając bądź skracając okno Form1) :

Obrazek

Nie fajne co? xd Pora odczytać pierwsze wartości z klienta Tibii. W tym celu deklarujemy zmienne globalne.
Robimy to w ten sposób:
Szukasz
[CODE]var
Form1: TForm1;[/CODE] - (zmienne globalne)

I pod nimi wpisujesz:

[CODE]
const
//adresy wartosci postaci
Player_ClubPerc = $60EA60;
Player_SwordPerc = $60EA64;
Player_AxePerc = $60EA68;
Player_DistnacePerc = $60EA6C;
Player_ShieldingPerc = $60EA70;
Player_FishingPerc = $60EA74;
Player_Fist = $60EA78;
Player_Club = $60EA7C;
Player_Sword = $60EA80;
Player_Axe = $60EA84;
Player_Distance = $60EA88;
Player_Shielding = $60EA8C;
Player_Fishing = $60EA90;
Player_Cap = $60EAA0;
Player_Stamina = $60EAA4;
Player_Soul = $60EAA8;
Player_ManaMax = $60EAAC;
Player_Mana = $60EAB0;
Player_MagicLevelPerc = $60EAB4;
Player_LevelPerc = $60EAB8;
Player_MagicLevel = $60EABC;
Player_Level = $60EAC0;
Player_Experience = $60EAC4;
Player_HpMax = $60EAC8;
Player_Hp = $60EACC;
Player_ID = $60EAD0;
//koniec - adresy wartosci postaci
[/CODE]

(daj save na wszeli wypadek Ctrl+S)

Skoro mamy już potrzebne adresy możemy wyciągać z nich dane :)
Teraz na Forme (na okienko bota) musimy wrzucić parę komponentów. Będą to komponenty TLabel(kilka) i TButton( tylko 2)
Jak je wrzucić?
Wybieramy z palety komponentów zakładkę "standard" i szukamy komponentu Label (ma obrazek litery A) teraz wystarczy na niego nacisnąć i przycisnąć Forme w miejscu w którym chcemy stworzyć komponent. (powtarzamy to 5 razy).
Potem w tej samej zakładce "standard" szukamy komponentu Button (przycisk z napisem OK) i robimy to samo tylko że 2 razy.
Wszystko wygląda teraz tak (Jeszcze nic nasz program nie zrobi :P):

Obrazek

Teraz zmienimy Caption Przycisków (ten tekst Button1 i Button2) na Start(button1) i Stop(button2)
Aby to zrobić musimy nacisnąć na button na formie w zakładce Properties poszukać Caption i zmienić Button1 na Start. Z drugim przyciskiem robimy to samo :P

Teraz Pora aby nasz bot odczytał wartości z danych adresów i po wciśnięciu przycisku pokazał je nam na formie (do tego służy labelx).

Naciskamy 2 razy na Button1 (czyli Start) Powinniśmy zobaczyć coś takiego

[CODE]procedure TForm1.Button1Click(Sender: TObject);
begin

end;[/CODE]

I między begin i end; wpisujemy

[CODE]label1.Caption:=inttostr(ReadMeminteger(Player_Level));
label2.Caption:=inttostr(ReadMeminteger(Player_MagicLevel));
label3.Caption:=inttostr(ReadMeminteger(Player_HP));
label4.Caption:=inttostr(ReadMeminteger(Player_Mana));
label5.Caption:=inttostr(ReadMeminteger(Player_Soul));[/CODE]

Teraz wciskamy ctrl+F9 potem ctrl+s potem F9 ;)
Po odpaleniu Tibii zalogowaniu się i naciśnięciu przycisku Start powinniśmy zobaczyć jak Label1 2 3 itp zmieniają się na nasz:
Level
Magic Level
Aktualne HP
Aktualna Mane
Aktualne Soule

Teraz wystarczy zrobić tak samo jak z Button1 tylko że w Button2(stop) onClick wpisać

[CODE]label1.Caption:=inttostr(0);
label2.Caption:=inttostr(0);
label3.Caption:=inttostr(0);
label4.Caption:=inttostr(0);
label5.Caption:=inttostr(0);[/CODE]

Teraz wciskamy ctrl+F9 potem ctrl+s potem F9 ;)

Odpalamy bota i przyciskiem Start możemy odczytać wartości i zapisać jako label1 2 3 itp a przyciskiem Stop możemy przestać je odczytywać i zapisać label 1 2 3 itp jako 0

Teraz wygląda to tak:

Obrazek


No tak. Wszystko jest ładnie i pięknie ale co nam z raz wczytanych danych? NIC xD No chyba że one się nie zmieniają ;P

Fajnie by było zrobić coś co cały czas odświeżało by te wartości. Do tego będzie nam potrzebny Timer.
Timer wstawia się tak samo jak inne komponenty ale jest on w zakładce system (taki zegarek). Wstawiamy go byle gdzie na Forme i naciskamy 2 razy. Pojawi się coś takiego:

[CODE]procedure TForm1.Timer1Timer(Sender: TObject);
begin

end;[/CODE]

Między Begin i End; wpisujemy

[CODE]label1.Caption:=inttostr(ReadMeminteger(Player_Level));
label2.Caption:=inttostr(ReadMeminteger(Player_MagicLevel));
label3.Caption:=inttostr(ReadMeminteger(Player_HP));
label4.Caption:=inttostr(ReadMeminteger(Player_Mana));
label5.Caption:=inttostr(ReadMeminteger(Player_Soul));[/CODE]

Jak to działa? Po otwarciu naszego programu Timer będzie co 1000 ms odczytywał nasze dane i wpisywał je do labeli.

Pora zmodyfikować troszkę Buttony.

Naciskasz Button1 (Start) 2 razy i wywalamy wszystko co jest pomiędzy Begin End; Zamiast tego wpisujemy to:
[CODE]Timer1.Enabled:=true;[/CODE]
W Button2 też wywalamy tekst i wpisujemy:
[CODE]Timer1.Enabled:=false;[/CODE]

Co to jest?

Button1 uaktywnia Timer1 (sprawia że ten odczytuje wartości) Button2 zatrzymuje Timer1. Trochę angielskiego i idzie się domyślić ;P
Afa no i jeszcze najważniejsze‚ musimy zrobić żeby nasz timer od początku był nieaktywny (żeby można było go aktywować przyciskiem) bo inaczej przycisk Start był by zbędny.
Po lewej stronie mamy okno Object TreeView szukamy Timer1 naciskamy na niego i w zakładce Properties (okno niżej) szukamy Enabled. Zmieniamy tą wartość na False. Od teraz Timer po uruchomieniu programu jest nie aktywny‚ a wartość enabled zmieniają Buttony.

Wszystko wygląda tak:

Obrazek



Dobra nadszedł czas abo dopisać to i owo. (znalazłem wenę)

Dobra to były dane które można po prostu odczytać‚ niektóre z nich trzeba albo można jednak znaleźć na battle liście. Oto kilka nowych stałych którymi uzypełnimy nasz program.

[CODE]BATTLELIST_START = $60EB30 + 4;
BATTLELIST_END = $6148F4;[/CODE]

Dlaczego dodałem do battlelist start 4? Z prostej przyczyny‚ chciałem aby nick był czytany jako pierwszy z battle list :) Oto obrazowe przedstawienie battle listy.


|-----------------|---------------|---------------| itp
| info o postaci 1 | info o postaci 2 | info o postaci 3 | itp

Te zielone kreski to właśnie odległości między postaciami. Na nich zapisane są wszystkie informacje o postaci (od id do tego czy postać idzie czy nie). Taka jedna odległość to 160. I tak zapisane są postacie od początku battle list (Battlelist_Start) do końca (BattleList_end). Teraz jak zrobić żeby odczytać jakąś daną z battle list? Musimy zrobić pętle.

Tu strasznie pomagam nam ID naszej postaci. Jak już wspomniałem wcześniej można je odczytać z adresu (Player_ID = $60EAD0;) oraz z battle list.

Oto odległości na od nicku postaci (dlatego dodałem do nicku 4 żeby mógł być pierwszą wartością). Dodajemy do stałych

[CODE]
Distance_ID= -4;
Distance_Type = -1;
Distance_Name= -0;
Distance_X = 32;
Distance_Y = 36;
Distance_Z = 40;
Distance_HorizScreenOffset = 44;
Distance_VertScreenOffset = 48;
Distance_Chameleon = 60;
Distance_Chameleon2 = 92;
Distance_IsWalking = 72;
Distance_Direction = 76;
Distance_Outfit = 92;
Distance_OutfitHead = 96;
Distance_OutfitBody = 100;
Distance_OutfitLegs = 104;
Distance_OutfitFeet = 108;
Distance_OutfitAddon = 112;
Distance_LightColor1 = 121;
Distance_LightColor2 = 122;
Distance_LightPattern = 123;
Distance_BlackSquare = 128;
Distance_HP = 132;
Distance_WalkSpeed = 136;
Distance_IsVisible = 140;
Distance_Skull = 144;
Distance_Party = 148;[/CODE]

Jak widzicie nasze id można też odczytać z odległości -4 od nicku. No i wszystko było by fajnie gdyby nasz nick był pierwszy na liście. Niestety tak nie jest :)

Teraz zrobimy jedną funkcję która odczyta za nas ważniejsze info o postaci bez konieczności przeszukiwania za każdym razem battle.

Otwieramy nasz programik. Szukamy miejsca
// Koniec - Funkcje czytające
i pod nim wpisujemy
//BattleList - Czytanie

I wklepujemy tam coś takiego

[CODE]
function pozycja:integer;
var
i‚id_battle‚id:integer;
begin
id:=readmeminteger(Player_id); //odczytanie naszego id z adresu
for i:=1 to 149 do //przeszukanie wszystkich pozycji na battle list (minimalna 1 maxymanlna 149
Begin
id_battle:=Readmeminteger(Battlelist_start + (i*160)-4); //czytanie id z pozycji
if id_battle=ID then //jezeli id z battle list zgadza sie z id z adresu
Begin
Result :=i; //wtedy wynikiem funkcji jest nasza pozycja na battle
exit;
end;
end;
end;
[/CODE]

No tak ale co nam z naszej pozycji na battle? Bardzo dużo!!
Jeżeli ją znamy możemy czytać sobie wszystkie info dotyczące naszej postaci znajdujące się na battle. Oto przykład‚ chcesz odczytać nasz nick? Bardzo proszę
Dodajemy to na button i mamy odczytany nasz nick
[CODE]

showmessage(MemReadString(BattleList_Start+pozycja*160+Distance_name));[/CODE]

3. Ingerencja w Klienta

Na wstępie podam wam funkcje pozwalające zapisać dane w adresach pamięci.

[CODE]procedure MemWriteInteger(Address: Integer; buf: Integer; Length: DWORD);
var ProcID‚ THandle: Integer;
e: DWORD;
begin
GetWindowThreadProcessId(FindWindow('TibiaClient'‚Nil)‚ @ProcID);
THandle := OpenProcess(PROCESS_ALL_ACCESS‚ False‚ ProcID);
WriteProcessMemory(THandle‚ Ptr(Address)‚ @buf‚ Length‚ e);
CloseHandle(THandle);
end;



procedure MemWriteString(Address: Integer; buf: String; Length: DWORD);
var ProcID: Integer;
THandle: hWnd;
e: DWORD;
begin
GetWindowThreadProcessId(FindWindow('TibiaClient'‚Nil)‚ @ProcID);
THandle := OpenProcess(PROCESS_ALL_ACCESS‚ False‚ ProcID);
WriteProcessMemory(THandle‚ Pointer(Address)‚ PChar(buf)‚ Length‚ e);
CloseHandle(THandle);
end;[/CODE]

Jak używamy?
Przykład. Chcemy sobie zrobić fake screena i potrzebujemy zwiększyć nasze aktualne hp.
No więc‚ hp integer. Bierzemy MemWriteInteger
I robimy coś takiego

[CODE]MemWriteInteger(PLAYER_HPnowy_lvl1)[/CODE]

Adres pod którym chcemy coś zapisać
Wartość jaka ma zostać zapisana pod adresem
Długość zapisywanej wartości - np jeżeli 500 to 3 jeżeli 50 to 2

4. Pierwsze udogodnienia

Wiemy już jak zapisywać wartości i jak je odczytywać‚ wiemy też jak odczytać różne dane z battle list‚ teraz możemy zająć się czymś poważniejszym.

Zaczniemy od światła.

Dodajemy 2 nowe odległości do naszych stałych

[CODE]DISTANCE_LIGHT = $74;
DISTANCE_LIGHTCOLOR = $78;[/CODE]

Na początku po odpaleniu nie edytowanego klienta tibii powinniśmy mieć w tych wartościach 0

Light to poprostu wielkość a raczej ranga w której światło jest widziane do okoła nas
Color to poprostu kolor światła.

Największa ranga to 15 (cały ekran)
Czysty color to 250.

Aby nadpisać sobie światło dodajemy na forme Buttona‚ naciskamy go 2 razy i wpisujemy pomiędzy begin a edn;

[CODE]MemWriteInteger(battlelist_start+pozycja*160+distance_lightcolor‚250‚3);
MemWriteInteger(battlelist_start+pozycja*160+distance_light‚15‚2);
[/CODE]

Objaśniać tego chyba nie trzeba :)

Oto jak teraz powinno wyglądać nasze źródło

Source5. Pakiety

Teraz chyba najtrudniejsza (przynajmniej do wytłumaczenia) część poradnika. Zacznijmy może od tego żeby pobrać FreeProx

http://www.blackdtools.com/freedownloads.php

Czym jest freeproxy? Jest to darmowe narzędzie do przechwytywania pakietów wysyłanych i przysyłanych z Klienta do Serwera i na odwrót.

Jak odpalić i sprawdzić pakiet?
Uruchamiasz freeproxy‚ odpalasz Tibie logujesz się do gry z okienka freeproxy wybierasz "PROXY" i na górze po lewej zaznaczasz "Log Packets" Teraz wystarczy że poruszysz postacią powiedzmy w prawo a zobaczysz coś takiego

Obrazek

Tak wygląda pakiet odpowiedzialny za poruszenie postaci w prawo.

Jeżeli chcecie sprawdzić pakiet możecie wybrać z okienka Freeproxy
"TOOLS" zaznaczyć Send to Server nacisnąć SEND HEX... i wkleić pakiet :)

Tak wygląda pakiet już ładnie uzupełniony i z dodanym nagłówkiem (my tych shitów nie widzimy ale są one niezbędne) Do czasu aż sami nie nauczymy się uzupełniać pakietów pomoże nam w tym biblioteka packet.dll

http://www.speedyshare.com/631866607.html

Po co nam to? A właśnie po to żeby uzupełnić pakiet pustymi bitami oraz dodać do niego nagłówek. Bardzo upraszcza nam to wysyłanie pakietu. Żeby móc cokolwiek wysłać przy pomocy tej biblioteki musimy dodać odpowiednią procedurę do naszego projektu.

[CODE]procedure SendPacket(ProcessID: Cardinal; Packet: Pointer; Encrypt: Boolean; SafeArray: Boolean); stdcall; external 'packet.dll';
[/CODE]

Wygląda ona tak i dodajemy ją przed wszystkimi funkcjami które już do tej pory mamy.

Oto przykładowa funkcja wysyłająca do klienta pakiet wypowiadania tekstu

[CODE]procedure say(text:string);
var
PacketBuffer: array [0..200] of byte;
ProcessID: Cardinal;

begin
GetWindowThreadProcessId(FindWindow('TibiaClient'‚Nil)‚ @ProcessID); //pobranie id procesu Tibii

PacketBuffer[0] := Byte(Length(text) + 4); //tu okreslana jest dlugosc pakietu bez 0 i 1
PacketBuffer[1] := $00;
PacketBuffer[2] := $96;
PacketBuffer[3] := $01;
PacketBuffer[4] := Byte(Length(text));
PacketBuffer[5] := $00;
CopyMemory(@PacketBuffer[6]‚ @text[1]‚ Length(text));
SendPacket(ProcessID‚ @PacketBuffer‚ TRUE‚ FALSE); // tu program wysyla pakiet do programu z proces id = ProcessID
end;[/CODE]

Znając to wszystko możemy napisać już prosty spell caster :)

Zaczniemy od wstawienia Timera na forme. Ustawiamy jego Enabled na "FALSE" (po to aby działał dopiero po naciśnięciu przycisku).

Teraz wrzucamy na formę komponent TEdit. Zakładka Standard obrazek z "ab". Wrzucamy też kolejnego Buttona. Ostatnim potrzebnym komponentem jest TSpinEdit‚ zakładka "Samples" czwarty od lewej. Mając już wszystkie potrzebne komponenty możemy przystąpić do pisania.


Naciskamy 2 razy na timer i zaznaczamy begin oraz end; w ich miejsce wklejamy to:

[CODE]var
mana:integer;
begin
mana:=readmeminteger(player_mana);

if mana > spinedit1.Value then
begin
say(edit1.Text);
end;

end;[/CODE]

Jak to działa? Timer pobiera naszą aktualną mane. I jeżeli nasza mana jest większa od wartości wpisanej w SpinEdit1 wtedy wypowiada słowa z okienka Edit1 (przykładowo czar).

Teraz musimy jeszcze zrobić button który uaktywni Timer. W tym celu naciskamy 2 razy na Button i między begin a end; dodajemy coś takiego:

[CODE]
If (Button4.Caption = 'Start') then
begin
timer2.Enabled := True;
Button4.Caption := 'Stop';
end
Else
if (Button4.Caption = 'Stop') then
begin
timer2.Enabled := False;
Button4.Caption := 'Start';
end;[/CODE]

A Caption Buttona (zakładka "Properties" piąte okno od góry) zmieniamy na 'Start'.

Jak to działa? Po naciśnięciu przycisku program sprawdzi czy ma on caption Start albo Stop i w zależności od tego co znajdzie zmieni Enabled Timera na True bądź False.

Kompilujemy program i testujemy ;)

Teraz nasz program powinien wyglądać właśnie tak:

Obrazek

A oto jego source:
Source

6. Inne funkcje na pakietach

Picie mana fluidu:

[CODE]procedure Manas;
var
PacketBuffer: array [0..200] of byte;
ProcessID: Cardinal;
begin

GetWindowThreadProcessId(FindWindow('TibiaClient'‚Nil)‚ @ProcessID);
PacketBuffer[0] := $0D;
PacketBuffer[1] := $00;
PacketBuffer[2] := $84;
PacketBuffer[3] := $FF;
PacketBuffer[4] := $FF;
PacketBuffer[5] := $00;
PacketBuffer[6] := $00;
PacketBuffer[7] := $00;
PacketBuffer[8] := $3A;
PacketBuffer[9] := $0B;
PacketBuffer[10] := $0A;
PacketBuffer[11] := $09;
PacketBuffer[12] := $D6;
PacketBuffer[13] := $95;
PacketBuffer[14] := $00;
SendPacket(ProcessID‚ @PacketBuffer‚ TRUE‚ FALSE);
sleep(500);
end;[/CODE]

To jest tylko przykład. Możecie sami wysniffować sobie pakiety za pomocą Freeproxy opisanego na początku rozdziału piątego. Wystarczy potem że kolejne wartości podstawicie za PacketBuffer[x] gdzie "x" to liczba tych wartości‚ zaczynająca się od 0 :)
« Powrót do listy Artykułów
<a href="http://www.game-advertising-online.com/" target=_blank>Game Advertising Online</a><br> banner requires iframes