IDA斷點和搜索


一、斷點

調試很重要一點是下斷點,看看IDA提供的功能,本來已經和WinDbg一樣強了。

官方文檔的變化

Edit breakpoint

Action    name: BreakpointEdit

Condition(6.5及之前版本)

  This IDC expression will be evaluated each time the breakpoint
  is reached. If the expression returns true, the debugger will execute the
  selected actions. Please note that you can use the register names in the
  IDC scripts when the debugger is active. Tests like this would be ok,
  for example: EAX == EBX+5 or Dword(ESP+0x10) == 34

Condition(6.6版本開始)

  This IDC expression will be evaluated each time the breakpoint
  is reached. If the expression returns true (non-zero), the debugger will execute the
  selected actions. Please note that you can use the register names in the
  IDC scripts when the debugger is active. Tests like this are allowed,
  for example: EAX == EBX+5 or Dword(ESP+0x10) == 34
  You can also use the "..." button to enter a multiline condition, or specify
  another scripting language to use. See here for
  more info.

Breakpoint conditions

You can use the "Condition" field of the breakpoint properties to enter an expression which is evaluated when the breakpoint is hit. It can be either an actual condition or just any valid code in IDC or another supported scripting language syntax. By using the "..." button, you can open a multi-line editor for the condtition and switch the scripting language used for evaluating it.

Expressions

  If you enter an expression, the result will be used to determine whether
  the selected actions are exectuted. Some examples of IDC expressions:
  Check if EAX is equal to 5:
    EAX==5
  Check if the first argument to the function is 1:
    Dword(ESP)==1
  Interpret the second argument to the function as a pointer to Unicode string, print it,
  and return 0 (so that the execution continues immediately):
    Message("Filename: %s\n", GetString(Dword(ESP+4), -1, ASCSTR_UNICODE)), 0
  Set EAX to 0 and continue:
    EAX=0,0
Statements
  You can enter several statements in the multi-line editor. If the last one is a 'return' statement,
  it is used as the result of the condition. Otherwise the condition is assumed to return 0.

 

可以看出新變化,支持多行編輯了,更好更方便更加強大。舉得例子也讓我想起逗號表示式了,也就是不斷點打印日志可以使用這種方式。

逗號表達式
表達式1,表達式2,表達式3,...... ,表達式n
逗號表達式的要領:
(1) 逗號表達式的運算過程為:從左往右逐個計算表達式。
(2) 逗號表達式作為一個整體,它的值為最后一個表達式(也即表達式n)的值。
(3) 逗號 運算符的優先級別在所有運算符中最低。
如:(3+5,6+8)的值是14,(a=3*5,a*4)的值是60。

 

官方網站更新介紹:https://www.hex-rays.com/products/ida/6.6/,里面有許多改變,這里看編輯條件斷點。

Multiline breakpoint conditions

Python users will love this: now it is possible to write a multiline condition right in the 'edit breakpoint' dialog box. IDA even accepts function definitions there!

Multiline breakpoint conditions in IDA6.6

 

以前的

1、斷點:

參考:自帶文檔,調試菜單(Debugger submenu)-斷點子菜單(Breakpoints submenu)-編輯斷點(Edit breakpoint)章節和IDC之表達式(IDC: Expressions)一章

條件斷點,可以輸入一個IDC表達式,如果在調試狀態下可以使用寄存器名字。

Condition

  This IDC expression will be evaluated each time the breakpoint
  is reached. If the expression returns true, the debugger will execute the
  selected actions. Please note that you can use the register names in the
  IDC scripts when the debugger is active. Tests like this would be ok,
  for example: EAX == EBX+5 or Dword(ESP+0x10) == 34

案例1:自定義打印跟蹤執行某條語句時的各種值。

Alphabetical list of IDC functions

The following conventions are used in the function descriptions:

  'ea' is a linear address
  'success' is 0 if a function fails, 1 otherwise
  'void' means that function returns no meaningful value (always 0)
  'anyvalue' means that function may return value of any type

一個永遠返回假的條件表達式:0 * Message("%s = %d\n", atoa(Dword(R2+0x10)), R2+0x20)

這里我試過,需要與0相乘,確保假。

 

遠程調試,字符串指針R2+0x10的值是"crack"的表達式

'c' == DbgByte(DbgDword(R2+0x10)) && 'r' == DbgByte(1+DbgDword(R2+0x10)) && 'a' == DbgByte(2+DbgDword(R2+0x10)) && 'c' == DbgByte(3+DbgDword(R2+0x10)) && 'k' == DbgByte(4+DbgDword(R2+0x10))

案例2:根據前一條語句的某些值來對某語句下條件斷點。

CODE:00234EC8 loc_234EC8:                             ; CODE XREF: sub_234DD8+CB↑j
CODE:00234EC8 mov     eax, edi
CODE:00234ECA call    sub_193ED4
CODE:00234ECF push    eax                             ; hWnd
CODE:00234ED0 call    GetWindowTextLengthW
CODE:00234ED5 mov     edx, eax
CODE:00234ED7 inc     edx
CODE:00234ED8 mov     eax, esi
CODE:00234EDA call    sub_E48AC
CODE:00234EDF mov     eax, [esi]
CODE:00234EE1 call    sub_E4544
CODE:00234EE6 push    eax                             ; nMaxCount
CODE:00234EE7 mov     eax, [esi]
CODE:00234EE9 call    sub_E4534
CODE:00234EEE push    eax                             ; lpString 壓入第二參數,緩沖區指針地址,可利用條件斷點保存EAX值
CODE:00234EEF mov     eax, edi
CODE:00234EF1 call    sub_193ED4
CODE:00234EF6 push    eax                             ; hWnd
CODE:00234EF7 call    GetWindowTextW
CODE:00234EFC mov     eax, [esi]                      ; 執行完GetWindowTextW后在這里利用條件斷點查看緩沖區
CODE:00234EFE call    sub_E4544
CODE:00234F03 mov     edx, eax
CODE:00234F05 dec     edx
CODE:00234F06 mov     eax, esi
CODE:00234F08 call    sub_E48AC

 

在執行完GetWindowTextW想看里的內容或者根據lpString來下條件斷點。可以這樣:

1、在IDA底部的IDC命令行聲明一個全局變量:extern lpString;

2、在CODE:00234EEE處下表達式始終為假的條件斷點:0 * (lpString = EAX) || 0 * Message("EAX = %x, lpString = %x\n", EAX, lpString)

3、在CODE:00234EFC處下條件斷點,表達式為:0 * Message("GetString(Address_%x)=%s\n", lpString, GetString(Dword(lpString),-1, ASCSTR_UNICODE))

結果打印類似如下:

EAX = 7d71a5c, lpString = 7d71a5c

GetString(Address_7d71a5c)=

EAX = 7d5ebb4, lpString = 7d5ebb4

GetString(Address_7d5ebb4)=

在IDA底部的IDC命令行輸入lpString執行,查看lpString,嗯起作用了

IDC>lpString

131460020. 7D5EBB4h 765365664o 00000111110101011110101110110100b '措'

 

在CODE:00234EFC處下條件斷點,表達式為:

0 * Message("GetString(%x)=%s\n", lpString, GetString(lpString,-1, ASCSTR_UNICODE))

EAX = 7d71a5c, lpString = 7d71a5c

GetString(7d71a5c)=

EAX = 1377e64, lpString = 1377e64

GetString(1377e64)=Incomplete or Invalid Registration Key

EAX = 7d71a5c, lpString = 7d71a5c

GetString(7d71a5c)=&OK

字符串比較斷點:

斷點地址 User32.dll BOOL SetWindowText(HWND hwnd,LPCTSTR lpString);

斷點條件 0*Message("wchar(%x)=%s\n", Dword(ESP+8), GetString(Dword(ESP+8),-1, ASCSTR_UNICODE)) || GetString(Dword(ESP+8),-1, ASCSTR_UNICODE) == "Incomplete or Invalid Registration Key"

其中,邏輯||前為打印調用的歷史記錄。

2、程式化下條件斷點

見文檔Breakpoint handling functions一章

// Set breakpoint condition
//      address  - any address in the breakpoint range
//      cnd      - breakpoint condition
//      is_lowcnd- 0:regular condition,1:low level condition
// Returns: success

success SetBptCndEx(long ea, string cnd, long is_lowcnd);
#define SetBptCnd(ea, cnd) SetBptCndEx(ea, cnd, 0)

 

Debugger: control

***********************************************
Execute one instruction in the current thread.
Other threads are kept suspended.
//
NOTE
  You must call GetDebuggerEvent() after this call
  in order to find out what happened. Normally you will
  get the STEP event but other events are possible (for example,
  an exception might occur or the process might exit).
  This remark applies to all execution control functions.
  The event codes depend on the issued command.
returns: success

success StepInto(void);

      IDA 5.2持調試器除了支持以往的事件的模型,還允許設計一個順序
執行(線性模型)的IDC 腳本來控制調試器。以往的基於事件的模型依然可用,同時也可通過使
用 get_debugger_event()這個函數來支持簡單的線性模型。這個函數暫停插件(或腳本)
的執行直到一個新的調試器時間發生。使用者可以指定他是只對進程掛起事件感興趣或是對
所有事件。也可以進行定時設置,如果沒有其它事件發生,超時后程序可以繼續執行。

 

#include <idc.idc> 

//-------------------------------------------------------------------------- 
static main() 
{
    auto code, bptea_some_addrese;   

    AppBpt(bptea_some_addrese); // 在某地址下斷點 
    StartDebugger("","",""); // 調試start debugger with default params  
    code = GetDebuggerEvent(WFNE_SUSP, -1);  // 等待斷點發生... and wait for bpt 
    if ( code <= 0 )
        return Failed(code); 

    Message ("Stopped at %a, event code is %x\n", GetEventEA(), GetEventId());  // 打印消息

    StepInto();                      // 扮演跟進行動 request a single step 
    GetDebuggerEvent(WFNE_SUSP, -1); // ... and wait for app to execute 
    StepInto();                       // request a single step 
    GetDebuggerEvent(WFNE_SUSP, -1); // ... and wait for app to execute
    DelBpt(bptea);
} 
//-------------------------------------------------------------------------- 

// Print an failure message 
static Failed(code) 
{ 
    Warning("Failed, sorry (code %d)", code); 
    return 0; 
}

 UUNP 解壓器插件的核心功能

http://blog.csdn.net/eqera/article/details/8239505

#include <idc.idc> 
 
//-------------------------------------------------------------------------- 
static main() 
{ 
  auto ea, bptea, tea1, tea2, code, minea, maxea; 
  auto r_esp, r_eip, caller, funcname; 
 
  // Calculate the target IP range. It is the first segment. 
  // As soon as the EIP register points to this range, we assume that 
  // the unpacker has finished its work. 
  tea1 = FirstSeg(); 
  tea2 = SegEnd(tea1); 
 
  // Calculate the current module boundaries. Any calls to GetProcAddress 
  // outside of these boundaries will be ignored. 
  minea = MinEA(); 
  maxea = MaxEA(); 
 
  // Launch the debugger and run until the entry point 
  if ( !RunTo(BeginEA()) ) 
    return Failed(-1); 
 
  // Wait for the process to stop at the entry point 
  code = GetDebuggerEvent(WFNE_SUSP, -1); 
  if ( code <= 0 ) 
    return Failed(code); 
 
  // Set a breakpoint at GetProcAddress 
  bptea = LocByName("kernel32_GetProcAddress"); 
  if ( bptea == BADADDR ) 
    return Warning("Could not locate GetProcAddress"); 
  AddBpt(bptea); 
 
  while ( 1 ) 
  { 
    // resume the execution and wait until the unpacker calls GetProcAddress 
    code = GetDebuggerEvent(WFNE_SUSP|WFNE_CONT, -1); 
    if ( code <= 0 ) 
      return Failed(code); 
 
    // check the caller, it must be from our module 
     r_esp = GetRegValue("ESP"); 
    caller = Dword(r_esp);
if ( caller < minea || caller >= maxea ) 
      continue; 
 
    // if the function name passed to GetProcAddress is not in the ignore-list, 
    // then switch to the trace mode 
    funcname = GetString(Dword(r_esp+8), -1, ASCSTR_C); 
    // ignore some api calls because they might be used by the unpacker 
    if ( funcname == "VirtualAlloc" ) 
      continue; 
    if ( funcname == "VirtualFree" ) 
      continue; 
 
    // A call to GetProcAddress() probably means that the program has been 
    // unpacked in the memory and now is setting up its import table 
    break; 
  } 
 
  // trace the program in the single step mode until we jump to 
  // the area with the original entry point. 
  DelBpt(bptea); 
  EnableTracing(TRACE_STEP, 1); 
  for ( code = GetDebuggerEvent(WFNE_ANY|WFNE_CONT, -1); // resume 
        code > 0; 
        code = GetDebuggerEvent(WFNE_ANY, -1) ) 
  { 
    r_eip = GetEventEa(); 
    if ( r_eip >= tea1 && r_eip < tea2 ) 
      break; 
  } 
  if ( code <= 0 ) 
    return Failed(code); 
 
  // as soon as the current ip belongs OEP area, suspend the execution and 
  // inform the user 
  PauseProcess(); 
  code = GetDebuggerEvent(WFNE_SUSP, -1); 
  if ( code <= 0 ) 
    return Failed(code); 
 
  EnableTracing(TRACE_STEP, 0); 
 
  // Clean up the disassembly so it looks nicer 
  MakeUnknown(tea1, tea2-tea1, DOUNK_EXPAND|DOUNK_DELNAMES); 
  MakeCode(r_eip);
AutoMark2(tea1, tea2, AU_USED); 
  AutoMark2(tea1, tea2, AU_FINAL); 
  TakeMemorySnapshot(1); 
  MakeName(r_eip, "real_start"); 
  Warning("Successfully traced to the completion of the unpacker code\n" 
          "Please rebuild the import table using renimp.idc\n" 
          "before stopping the debugger"); 
} 
//-------------------------------------------------------------------------- 
// Print an failure message 
static Failed(code) 
{ 
  Warning("Failed to unpack the file, sorry (code %d)", code); 
  return 0; 
} 

 

 

二、搜索

addr = FindBinary(0, SEARCH_DOWN, "31 32 33 34 35 36 37 38 39");


#ea =  FindText(ea, SEARCH_NEXT | SEARCH_REGEX, 0, 0, "test *[a-zA-Z]*, +[a-zA-Z]*")

MinEA() 等價於 GetLongPrm(INF_MIN_EA) 
而INF_MIN_EA // int32; The lowest address used // in the program

//
IDC>auto ea_result = FindText(MinEA() ,SEARCH_DOWN|SEARCH_NEXT, 0, 0, "478467622");  Message("%s %x\n", BADADDR == ea_result ? "bad" : "ok",  ea_result); 
bad ffffffff

//查找mov     dword ptr [eax+1Ch], offset sub_11010類似這種形式的指令
IDC>auto ea = 0; ea = FindText(ea,  SEARCH_DOWN |SEARCH_NEXT | SEARCH_REGEX, 0, 0, "mov +dword ptr \\[[a-zA-Z]+\\+[a-zA-Z0-9_ ]+h\\],[a-zA-Z0-9_ ]*"); Message("Find in %x\n", ea); if(BADADDR != ea) {auto op2_addr = GetOperandValue(ea,1); Message("op2 address is %x\n", op2_addr);}
Find in 30801855  //雙擊這里自動定位代碼
op2 address is 24

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM