2015-06-18 15 views
5

Mam instrukcję śledzenia i chcę wyodrębnić wywołania funkcji i zwraca.Różnice między wywołaniem, naciśnięciem + ret i naciśnięciem + przeskoku w zespole

Okazało się, że oprócz call instrukcji, push + jmp i push + ret może być stosowany do wywołania funkcji? Na początku chcę mieć pewność, że to prawda? a jeśli tak, jakie są różnice między nimi?

Także jeśli push + ret jest rodzajem połączenia, więc jaki byłby koniec lub powrót funkcji? Czy widzisz tylko ret bez instrukcji ?

Odpowiedz

4

W uproszczeniu:

połączeń adres

To będzie apelować zaktualizowany licznik programu (co wskazuje z instrukcją po call) na stosie, a następnie przejść do adres wskazanym (mogą być stosowane tryby adresowania).

ret

Ta instrukcja wewnętrznie wyskakuje i adres ze stosu i skacze do niej. To jest ładnie dopasowany do call, dzięki czemu może wrócić do instrukcji po poprzednim call.

jmp adres

To po prostu przeskakuje do podanej adres (z pewnymi tryby adresowania). W ogóle nic nie robi ze stosem.


Tak, można też to zrobić:

push address 
ret 

Która pojawi się i skakać do adres że został zepchnięty na stosie w sposób opisany powyżej. Jest to sprytny sposób na pośredni skok w mikroprocesorze, który nie obsługuje pośrednich trybów adresowania w instrukcjach skoku.

Kolejność:

push address 
jmp someplace 

po prostu przeskoczyć do gdzieś i nie wpływa na stos lub użyj adres że został zepchnięty na stos. Jeśli adres jest instrukcją po jmp, jest to mniej więcej odpowiednik call someplace.

Dla zestawów instrukcji, które nie obsługują pośredni skok adresowania, widziałem to miły mały obejście:

push address 
ret 

jaki przeskoczy na cokolwiek address jest.

+0

Nietypowe odmiany tych znaków są często używane, gdy autor chce ukryć prawdziwą funkcjonalność kodu (np. Złośliwe oprogramowanie komercyjne "chronione przed kopiowaniem"). –

+0

Czy 'ret' w zasadzie nie jest' pop i przeskocz pośrednio do wyskakującego adresu '? –

+0

@JohnHascall tak, to jest ... "duh" z mojej strony. : p Myślałem "nie", "nie", "nie". :) – lurker

6

Tak, masz rację.

Po wydaniu call, adres powrotu umieszczony na stosie to kolejny adres, na którym należy kontynuować wykonywanie (adres bezpośrednio po bieżącej instrukcji). W istocie jest to atomiczny push, po którym następuje jmp.

Oznacza to, że jeśli ręcznie push a następnie jmp funkcja że wskoczyć później mogą ret i pod warunkiem, wszystko stos dostęp do funkcji jest zrównoważony, powróci do adresu, który wcześniej wciśnięty.

Podobnie można push, a następnie ret symulować powrót połączenia, ale to nie ustawi cię, aby móc później wrócić ponownie. Tego typu zachowanie jest zwykle wykonywane w celu wyrzucenia dezasemblerów, co utrudnia ustalenie, do którego adresu faktycznie prowadzi dany kod za pomocą prostego deasemblera.

+0

"Ten typ zachowania jest częściej wykonywany, aby wyrzucić dezasemblerów" Czy wiesz, że IDA Pro ma jakąkolwiek funkcjonalność, aby poprawnie interpretować te taktyki jako połączenia/zwroty? Z ogólnej perspektywy, w jakim kierunku chciałbyś polecić rozmontowanie kodu, który stosuje tę taktykę zaciemniania? edytuj: trochę więcej wyszukiwania dało ten wątek, który odwołuje się do twojej odpowiedzi i odpowiada na moje pytanie: http://reverseengineering.stackexchange.com/questions/10911/automatically-decode-pushret-call-into-jmp – SullX

Powiązane problemy