[C/Assembler] CALL i adres powrotu

[C/Assembler] CALL i adres powrotu
0

Witam.

Próbuję zrobić hooka na funkcje w assemblerze. Robie to tak, że w funkcji, którą chcę przechwycić wycinam ze dwie instrukcje ( kilka bajtów ) i daje tam CALL adresMojejFunkcji. Moja funkcja jest wypełniona nopami, więc moge spokojnie tam skopiować kod, który wyciąłem. W ten sposób nie ma żadnych strat kodu i w mojej funkcji moge dać kod, który wykona sie po wywołaniu przechwyconej funkcji.

Wygląda to mniej więcej tak

// Początek funkcji, którą chce przechwycić

Kopiuj
PUSH EBP
MOV EBP, ESP

// tutaj jakis przykładowe kod na początku funkcji
MOV test, 123
MOV zmienna, 123456

wycinam:

Kopiuj
MOV test, 123
MOV zmienna, 123456

i zastepuje tam na call, wygląda to teraz mniej więcej tak:

Kopiuj
PUSH EBP
MOV EBP, ESP

CALL adresMojejFunkcji

a tu zawartosc mojej funkcji po wklejeniu tam mojego kodu.

Kopiuj
PUSH EBP
MOV EBP, ESP

MOV test, 123
MOV zmienna, 123456

nop
nop
nop
nop
nop

RETN

Teraz wystarczyło by jakoś powrócić do funkcji.

I mam pytanie:

Co oznacza PUSH EBP i MOV EBP, ESP na początku każdej funkcji (w OllyDbg) ?
Jest to wrzucenie na stos adresu powrotu?

Jeżeli tak, to jest problem.

Gdyby ten kod, który musze wkleić

Kopiuj
MOV test, 123
MOV zmienna, 123456

byłby inny np.

Kopiuj
PUSH test
PUSH 93

to moja funkcja wyglądała by tak:

Kopiuj
PUSH EBP
MOV EBP, ESP

PUSH test
PUSH 93

nop
nop
nop
nop
nop

RETN

I jeżeli adres powrotu był na stosie, to 93 i zawartość test będzie wyżej na stosie, więc chyba nici z adresu powrotu?

Jak mogę zrobić poprawnie powrót do przechwytującej funkcji?

Z góry dziękuje za pomoc

dzejo
  • Rejestracja:ponad 18 lat
  • Ostatnio:prawie 12 lat
  • Postów:787
0

Ale o co chodzi ?
Jak wklejasz call funkcja która jest ( jeśli) prawidłowo napisana to kod
ma powrócić do instrukcji następnej po call i opuścić twoją ->adresMojejFunkcji ,
nie ma tu żadnego wklejania kodu zawartego w adresMojejFunkcji .
Jak wklejasz na żywca kod z push to też nie ma znaczenia bo stos
jest zachowany tyle że nigdzie nie wracasz tylko następuje dalsze wykonanie kodu .
(oczywiście trzeba wyrównać stos instrukcjami pop)


MA
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad 15 lat
  • Postów:501
0

To? Ustawienie ramki stosu, która pozwala na łatwiejsze odwoływanie się do zmiennych zrobionych na stosie. Przy wychodzeniu należy ją zwinąć -

Kopiuj
mov esp, ebp
pop ebp

albo

Kopiuj
leave

A adres powrotu sam się odkłada przy CALLu.

SA
  • Rejestracja:prawie 21 lat
  • Ostatnio:ponad 9 lat
  • Postów:513
0

Co do rejestru ebp, to trzeba porządnie wyjaśnić o co chodzi.
Dostęp do parametrów zazwyczaj jest możliwy poprzez rejestr esp: [esp+4] to pierwszy parametr, [esp+8] to drugi itd. Wszystko dobrze póki ESP nie zmieni się, a zmieni się na przykład w przypadku odwołania do innej funkcji z parametrami:

Kopiuj
push dword [esp+4] ; arg0
; esp zmienił się o -4
push dword [esp+8] ; arg1
; esp ponownie zmienił się o -4
call funkcja

Co tu jest źle? Ano pierwszy push zmienił rejestr esp, więc drugi push wcale nie zaadresuje drugiego parametru tylko pierwszy, dlatego trzeba uwzględnić zmianę stosu w każdym następnym push:

Kopiuj
; uu,ii,oo,pp to offsety parametrów ze stosu: +4,+8,+12...
push dword [esp+uu] ;
push dword [esp+ii+4] ; dodatkowe +4
push dword [esp+oo+8] ; dodatkowe +8
push dword [esp+pp+12] ; dodatkowe +12
call funkcja

Równie dobrze będzie z innym rejestrem, ale tu już nie trzeba uwzględniać zmiany esp

Kopiuj
mov eax,esp
push dword [eax+4] ; arg0
push dword [eax+8] ; arg1
push dword [eax+12] ; arg2
call funkcja

W powyższym przykładzie esp się zmienia po każdym push, ale eax który pamięta jego oryginalną wartość jest stały, więc nie trzeba nic korygować.

Realny przykład - wrapper dla makra StrIntlEqNIW z shlwapi.h

Kopiuj
;#define StrIntlEqNIW(s1, s2, nChar) StrIsIntlEqualW(FALSE, s1, s2, nChar)

StrIntlEqNIW:
	invoke StrIsIntlEqualW, 0, [esp+4+8], [esp+8+4], [esp+12]
	ret    12 ; stdcall

Dlatego ktoś wpadł na pomysł by nie używać rejestru esp do adresowania parametrów funkcji, tylko innego rejestru, padło na EBP ponieważ kiedyś pewnie wydawał się zbędny:

Kopiuj
push ebp
mov ebp,esp

push dword[ebp+8] ; arg0
push dword[ebp+12] ; arg1
push dword[ebp+16] ; arg2
call funkcja
...
pop ebp
ret

Dodatkową zaletą jest możliwość zaalokowania pamięci na tymczasowe dane:

Kopiuj
push ebp
mov ebp,esp
sub esp, 32 ; liczba podzielna przez 4
...
mov esp,ebp
pop ebp
ret

Pierwsze 3 linie można zastąpić rozkazem enter 32,0 a dwie ostatnie (ale nie ret) leave

Kopiuj
enter 32,0
...
leave
ret

Tak zaalokowaną pamięc adresujesz podobnie za pomocą rejestru ebp, tyle że offset jest ujemny. [ebp-32] to początek tej pamięci, a [ebp-1] to koniec, ostatni dostępny bajt.

A na koniec - po co jest push/pop ebp. Zależnie od systemu operacyjnego na którym będzie pracowała Twoja funkcja, musisz zwrócić niektóre rejestry i flagi w postaci niezmienionej. Gdy używasz rejestru ebp do adresowania parametrów, to chyba nie chcesz by jakaś funkcja (którą wywołujesz) go zmieniła? Owszem może go zmienić, ale zanim powróci powinna wpisać do niego taką wartość jaka była na początku. No, chyba że wiesz, że funkcja A nie może tracić czasu na zachowywanie rejestrów, wtedy funkcja ją wywołująca powinna to robić.

MA
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad 15 lat
  • Postów:501
0

Wybrano ebp nie dlatego że wydawał się zbędny, a dlatego, że jeszcze za czasów trybu rzeczywistego domyślnym segmentem dla niego był SS (i ciągle jest).
Enter muli. Ręczna zabawa z push/mov/sub jest szybsza...

0

Wypisac w pamieci liczby podzielne przez 4,
podzielne przez 8 wypisac 2 razy
4, 8,8, 12,16,16, 20 ... ( do 100 ), podzieln

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)