Wywoływanie funkcji DLL'ki

Wywoływanie funkcji DLL'ki
bajos
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:UwUdź
  • Postów:267
0

Witam

Czy jest możliwość zrobienia czegoś takiego:

  • program gra.exe na przykład jakaś gra
  • biblioteka przykladowa.dll która ma w sobie funkcję, która wywołuje funkcje z pliku gra.exe.
  • launcher na przykład launcher.exe, który po odpaleniu injectuje przykladowa.dll do odpalonego gra.exe, ale dopiero po kliknięciu jakiegoś przycisku w tym launcherze wykona funkcję w DLL'ce na przykład ustawiającą jakiś pojazd w programie gra.exe.
    Chciałbym zrobić coś takiego, że tym launcherem był by na przykład klient multi-player i sterował by programem gra.exe przez tą DLL'kę. Da się coś takiego zrobić? Jak się to fachowo nazywa? :)

@refresh


128 postów [25.06.2015r. 21:03]
edytowany 1x, ostatnio: bajos
several
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 8 godzin
0
bajos napisał(a):

Da się coś takiego zrobić?

Chcesz wywoływać funkcje z dllki z innego procesu - ok, da się. Ale chyba kombinujesz coś za bardzo z z tym zewnętrzym ładowaniem dllki do innego procesu, dlaczego gra.exe nie może załadować sobie tej dllki sama? Sądzę, że Twój rzeczywisty problem może być rozwiązany prościej.


kq
Podejrzewam, że to ma być jakiś hack do gry, więc nie ma kontroli nad główną binarką.
several
Hm, to ma sens. Kiepskie z niego hakier w takim razie.
bajos
To nie ma być hack tylko chcę napisać multiplayer do sapera i chodzi mi, żeby ten multiplayer wywoływał przez dllkę różne funkcje w Saperze :).
several
Nawet jeśli chodzi o sapera to nadal jest to hack :) Jeśli na prawdę chcesz hackować sapera to nie ma co się odżegnywać, w końcu nikomu krzywdy nie zrobisz.
1

Pytanie: w jakim stopniu znasz assemblera, i w jakim stopniu sobie poradzisz z deasemblacją? Jeśli to nie jest dla ciebie problemem to łatwo to zrobisz w sumie.
Musisz zrobić kilka hooków na pamięć gry, i kiedy jest naciskany button, to coś się dzieje, i ty musisz wiedzieć co.
Wtedy w disassemblerze patrzysz sobie adres tam gdzie to jest wywoływane, robisz hooka, w którym calluje się zupełnie inna funkcja z argumentami również.
Jeśli dalej nie będziesz wiedział jak się za to zabrać, to napisz, to ci wyjaśnię na prostym przykładzie jak to zrobić.

bajos
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad rok
  • Lokalizacja:UwUdź
  • Postów:267
0

Dopiero się uczę NASM, ale z tym poradnikiem zrobiłem .dll do Sapera http://www.p-programowanie.pl/cpp/dll-injection-wywolywanie-funkcji-z-parametrami/ i chciałbym jej funkcję funkcja(); wywoływać z np. programu launcher.exe do programu gra.exe (Saper). @several gra.exe nie może sama załadować, ponieważ to "obcy" program, którego nie pisałem ja.


128 postów [25.06.2015r. 21:03]
mwl4
Zaraz pokażę ci jakiś przykład ;-)
mwl4
  • Rejestracja:około 12 lat
  • Ostatnio:około 12 godzin
  • Lokalizacja:Wrocław
  • Postów:399
2

Dobrze, więc mamy taki oto przykład gry:
http://pastebin.com/SgYWfMaQ
Proste, mamy dwa przyciski, jeden wywołuje jedną funkcje, drugi drugą. Druga funkcja ma argument który jest wyświetlany w MessageBoxie.
Naszym celem jest, aby klikając pierwszy przycisk, wykonywała się druga funkcja z naszym parametrem, ale i wykonywało swoją pierwszą funkcję później.
Żeby się do tego zabrać oczywiście potrzebujemy jakiegoś disassemblera, jedyne co mogę polecić to jest IDA, która jest darmowa, ale ja ci radzę zaopatrzyć się w IDĘ która wyciekła z ESETu, która posiada plugin pseudocodeu w C.
W tym kroku trzeba zaznaczyć, że posiadamy pdb, czyli taki plik odpadowy, w którym kompilator zapisuje różne rzeczy. I nie są to byle jakie śmieci, bo jest tam w zasadzie wszystko aby przeprowadzić pomyślną dekompilację programu. Ale nie łudźmy się że w jakiejkolwiek grze znajdziemy pdb. W 99.99999999% przypadkach jest tylko exe.
Więc kiedy ładujemy exeka do IDA, to IDA nas pyta czy załadować pdb, i my wybieramy NIE.
Kiedy już nam się do IDA wczyta nasza binarka, no to działamy.
Trzeba nam adres gdzie się wykonuje function1, lub sam adres function1, oraz adres function2. Lecz pamiętaj, że w większości przypadków exeki nie mają exportów, przez co nie wiadomo gdzie dana funkcja jest. Tzn. IDA sama rozpoznaje gdzie się funkcje zaczynają, a gdzie kończą po referencjach funkcji.
Stąd niektóre exeki potrafią się do IDA ładować po parenaście minut..
Oczywiście my nie będziemy rozkodowywali całego exeka linijka po linijce, ponieważ to nie ma sensu, poza tym, zajmie nam to na prawdę dużo czasu(mam na myśli dekady).
Na nasze szczęście IDA rozpoznaje stringi na podstawie jakiegoś tam algorytmu. Na podstawie stringów możemy dojść, gdzie ten string jest wykorzystywany, czyli jego referencja.
Udajemy się więc do karty stringów, jeśli jej nie masz to: View -> Open Subviews -> Strings. Teraz szukamy interesującego nas stringu.
Wiemy, że function1 wyświetla string: "Wykonalem function1", więc spróbujmy go wyszukać.

user image
Teraz klikamy na niego dwa razy lub enter, i powinno nas przenieść do karty IDA View:
user image
Po prawej od stringa, widzimy, że już się wyświetlił nam pierwsza referencja, czyli XRef: sub_401200, offset: 30.
Innym sposobem podpatrzenia Xrefów w tym miejscu, jest kliknięcie prawym na "aWykonalemFunct"(po prawej od adresu) i wybranie Jump to Xref to operand, wyświetla nam się lista i jeśli klikniemy na jakiś element dwa razy to nas przeniesie do adresu. I robimy tak.
user image
Teraz prawdopodobnie zastanawiasz się o co tutaj chodzi, dlaczego funkcja w której to jest to jest: int __stdcall sub_401200(HWND hWnd, int, int, int),
otóż, rozświetli ci sytuację pseudocode tej funkcji, który wygląda następująco:
user image
Jak nietrudno zauważyć, jest to nasze WndProc, a po prostu VC++ zrobił z function1 inline.
Często tak się może zdarzyć że VC++ nam zinlinuje funkcje, ale nie ma co się gniewać na niego.
Później natomiast doskonale widzimy, że jest obsługiwany drugi button, i możemy zauważyć, że sub_401349 to jest po prostu rand.
W zasadzie już mamy wszystkie potrzebne adresy:

.text:0040122C push 0 ; uType
.text:0040122E push 0 ; lpCaption
.text:00401230 push offset aWykonalemFunct ; "Wykonalem function1"
.text:00401235 push 0 ; hWnd
.text:00401237 call ds:MessageBoxA

oraz

.text:00401249 call sub_401349
.text:0040124E cdq
.text:0040124F mov ecx, 0Ah
.text:00401254 idiv ecx
.text:00401256 mov ecx, edx
.text:00401258 call sub_401000

Czyli już wiemy że sub_401000 to jest function2.
Przejdź teraz do sub_401000 podwójnie klikając na niego, lub enter i zobacz co tam jest ;-)
Teraz jedynie musimy wykonać jeden hook, będzie to zwykły jump, do funkcji naszej dllki w miejscu wykonania MessageBoxa, a w funkcji naszej dllki wywołać function2 z gry z naszym parametrem.
Jak tego dokonać? To jest proste. Jeśli ładujemy dllkę do pamięci gry to my już siedzimy w procesie. Co sprawia, że możemy kontrolować pamięć, nawet nie tylko tą która jest alokowana. Trzeba pamiętać że do pamięci wczytują się również instrukcje, i to z pamięci są one wykonywane. Więc pozmieniajmy trochę pamięć.
Musisz zrobić w kodzie dllki taką funkcję, która nie ma żadnych śmieci z kompilatora. Jedynie takie instrukcje które sam napiszesz.
Do tego przyda ci się _declspec(naked).
Pamiętaj również, że callując własną funkcję w kodzie gry, musisz uważać aby nie ponaruszać rejestrów, bo jeśli zechcesz aby funkcja poszła dalej, to musisz bardzo na to uważać i korzystać z pushad oraz popad.
Pamiętaj również o tym, że jeśli chcesz wykonać coś na początku danej funkcji, ale później ona ma swobodnie iść do przodu, to musisz nadpisane instrukcje opcode przepisać.
Instrukcja JMP ma 5 bajtów jeśli bierzemy jmp-far. Czyli E9 00 00 00 00, i te zera to adres do funkcji.
Czyli musisz sobie napisać funkcję, która przyjmuje adres hooka, i adres funkcji do której ma skoczyć.
Czyli musisz mieć wolnych 5 bajtów, tzn. je nadpisać, a później jakoś wykonać.
Pamiętaj, że jakiekolwiek zabawy w offsetach nie są za dobrym pomysłem na hook, tzn, np:
.text:00401230 push offset aWykonalemFunct ; "Wykonalem function1"
.text:00401235 push 0 ; hWnd
.text:00401237 call ds:MessageBoxA

Tutaj ciężko ci będzie zrobić hooka, bo będziesz musiał zobaczyć offset tego stringa, póxniej offset MessageBoxa itd. a jest to dość niefajne.
Ale jeśli już na prawdę nie ma wyboru, no to niestety, trzeba to zrobić.
Adres hooka: 00401230. Adres stringa: 0040D518.
Oczywiście musimy także uwzględnić adres powrotny, bo jeśli mamy jmp, to on musi później znowu skoczyć tam gdzie była hookowana funkcja, czyli w naszym wypadku to jest:
00401235.
Należy wspomnieć, że w function2 VC++ zrobił psikusa i dla optymalizacji argument walnął do ecx.
Musimy zrobić sobie reprodukcję funkcji:
unsigned long sub_401000_addr = 0x00401000;
void sub_401000(unsigned long number)
{
_asm
{
mov ecx, number
call sub_401000_addr
}
}

Pamiętaj, że jeśli korzystasz z jmp, to nie odkłada się adres powrotu na stos. I w ten oto sposób, jeśli sub_401000 zechce powrócić, to nie zrobi tego w ten naszej funkcji sub_401000 tylko zrobi to w funkcji w której callowaliśmy naszą reprodukcję! Dlatego w tym przypadku użyłem call, jest lepiej.

To by było na tyle. Pamiętaj, że w jakiejkolwiek grze nie będziesz miał stringów z wykonania funkcji jak to tutaj zrobiliśmy. Tam jest ostre szukanie, ostre ogarnianie czegoś z niczego. Niektóre gry generują RTTI przez co masz bardzo ułatwioną pracę, ponieważ masz nazwy funkcji oraz informacje o klasach.

Cały kod źródłowy Gry, Launchera, i Dllki masz tutaj:
https://mega.co.nz/#!tVIGQbyD!fipaYTmycWbHPnfE9V3S3FkktbNhc_NH3vztfdxH6jY
mirror2:
http://www37.zippyshare.com/v/5616201/file.html

Powodzenia życzę w hackowaniu... yy.. znaczy w hookowaniu! :D


Asm/C/C++
edytowany 3x, ostatnio: mwl4
mwl4
Dodam, że kompilowane pod VS 2012 Express
bajos
Ale się rozpisałeś ;p. Można tutaj postawić jakieś piwo czy punkty lub coś w tym stylu? Btw. Ty to ten mwl4 z ETS2MP ;D?
mwl4
Tak, to ten sam... A co do punktów.. co mi z tych punktów? Pisząc tak obszerny post mam nadzieję, że ktoś kiedyś go zrozumie w 100% i wykorzysta jak się tylko da. Jakbym miał pomagać tylko za punkty, to po uj pomagać?
bajos
No tak ale jak można dać punkty to bym dał.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)