Вземете адреса на последната изпълнена инструкция в WinDBG

Обръщам win32 приложение.

Въпроси:

Докато отстранявате грешки в прог. открих, че броячът веднъж скача на адрес 0x0043D4A0. (Това е входна точка за функция).

  0043D4A0   51               PUSH ECX
  0043D4A1   8B51 04          MOV EDX,DWORD PTR DS:[ECX+4]
  0043D4A4   8B4424 0C        MOV EAX,DWORD PTR SS:[ESP+C]
  0043D4A8   3BC2             CMP EAX,EDX
  0043D4AA   890C24           MOV DWORD PTR SS:[ESP],ECX
  0043D4AD   7D 06            JGE SHORT PEiD.0043D4B5
  0043D4AF   32C0             XOR AL,AL
  0043D4B1   59               POP ECX

Сега искам да знам как мога да изпълня инструкцията Get the Address от предишната инструкция, преди да премина към тази точка 0x0043D4A0 с помощта на windbg. ТАКА, че мога да проследя откъде се извиква тази функция.

Благодаря предварително,


person Dev.K.    schedule 07.06.2013    source източник


Отговори (2)


Всеки път, когато се осъществи инструкция за извикване, адресът за връщане се избутва в стека непосредствено преди управлението да бъде прехвърлено към извиканата функция. Адресът за връщане е 4-те байта в ESP регистъра. Изпълнете командата dd на @ESP, след това изпълнете командата ub на стойността в @ESP. Това ще разглоби обратно от обратния адрес, което ще ви даде последователността от инструкции, извършени непосредствено преди и включително повикването.

person Steve Johnson    schedule 09.06.2013
comment
Ако приемем, че това е използвана инструкция CALL, адресът за връщане се избутва в стека и към целта се прескача. По този начин, за да видите адреса за връщане в дебъгера, трябва да изхвърлите ESP, а не ESP-4. Обърнете внимание, че не всички промени в контролния поток са CALL, поради което адресът за връщане в стека може да не е мястото за повикване на функцията. Виждате това често на x64, тъй като компилаторът иска да използва оптимизиране на опашката на извикването (т.е. замяна, връщане на Foo() с jmp Foo вместо извикване на Foo). - person snoone; 10.06.2013
comment
Благодаря за това. Прав си. Всъщност исках да кажа +4 така или иначе, но си прав. - person Steve Johnson; 11.06.2013

Използвай това:

? $previp

Указателят на инструкцията по време на предишното събитие. (Проникването в дебъгера се брои за събитие.)

Вижте това за други псевдо регистри

person EdChum    schedule 07.06.2013
comment
Всъщност искам да проследя формата къде се извиква тази функция, така че сложих BP @ 0043D4A0. Когато дебъгерът е поставен на пауза @ BP, който въведох? $previp n Получих 0x7c810856 Изчисляване на израз: 2088831062 = 7c810856 Така че, когато направих това, открих, че няма извикване/прескачане до адрес: 0043D4A0 0:001› u 7c810856 kernel32!BaseThreadStartThunk: 7c810856 33ed xor ebp,ebp 7c810858 53 натискане ebx 7c810859 50 push eax 7c81085a 6a00 push 0 7c81085c e973acffff jmp kernel32!BaseThreadStart (7c80b4d4) Каква може да е възможната причина за това? Благодаря, - person Dev.K.; 07.06.2013
comment

Ето правилния начин:

import java.util.*;
public class Coffee {
    public static void main(String args[]) {
        String s1="Cat";
        String s2="Dog";
        System.out.println(s1.compareTo(s2));
    }
}
- person Dev.K.; 08.06.2013
comment
Какво показва прозорецът за разглобяване или прозорецът на стека за извикване? Ако видите „няма предишен адрес“ в прозореца за разглобяване, можете ръчно да опитате да актуализирате отместването байт по байт, докато прозорецът за разглобяване може да генерира по-дълбокия стек за извикване за предишни инструкции вижте analyze-v.com/?p=31 като алтернатива можете да сканирате за този адрес с помощта на скрипт: blogs.msdn.com/b/debuggingtoolbox /архив/2007/07/20/ - person EdChum; 08.06.2013