2016-11-15 21 views
1

我想逆向工程的一些組件,我已經得到了這一點:GAS 86:讀取跳轉表/口譯switch語句

40073f: 89 45 fc    mov %eax,-0x4(%rbp) 
    400742: 83 7d fc 05    cmpl $0x5,-0x4(%rbp) 
    400746: 77 37     ja  40077f <f51+0x85> 
    400748: 8b 45 fc    mov -0x4(%rbp),%eax 
    40074b: 48 8b 04 c5 28 09 40 mov 0x400928(,%rax,8),%rax 
    400752: 00 
    400753: ff e0     jmpq *%rax 
    400755: b8 11 00 00 00   mov $0x11,%eax 
    40075a: eb 28     jmp 400784 <f51+0x8a> 
    40075c: b8 12 00 00 00   mov $0x12,%eax 
    400761: eb 21     jmp 400784 <f51+0x8a> 
    400763: b8 13 00 00 00   mov $0x13,%eax 
    400768: eb 1a     jmp 400784 <f51+0x8a> 
    40076a: b8 14 00 00 00   mov $0x14,%eax 
    40076f: eb 13     jmp 400784 <f51+0x8a> 
    400771: b8 15 00 00 00   mov $0x15,%eax 
    400776: eb 0c     jmp 400784 <f51+0x8a> 
    400778: b8 16 00 00 00   mov $0x16,%eax 
    40077d: eb 05     jmp 400784 <f51+0x8a> 
    40077f: b8 0a 00 00 00   mov $0xa,%eax 
    400784: 5d      pop %rbp 
    400785: c3      retq 

我可以看到我在尋找什麼在這裏是一個switch語句,默認情況下當-0x4(%rbp)> 5時,但我對幾條指令感到困惑:

是40074b只是跳到跳轉表上的某個位置並按下該指令換成rax,這樣我們可以跳到開關箱中的適當位置(這是行400753)?

在這種情況下,我不知道如何解釋我們的不同情況。如果我的理解是正確的跳轉表起始地址爲400928,去那裏我看到:

400928: 55      push %rbp 
    400929: 07      (bad) 
    40092a: 40 00 00    add %al,(%rax) 
    40092d: 00 00     add %al,(%rax) 
    40092f: 00 5c 07 40    add %bl,0x40(%rdi,%rax,1) 
    400933: 00 00     add %al,(%rax) 
    400935: 00 00     add %al,(%rax) 
    400937: 00 63 07    add %ah,0x7(%rbx) 
    40093a: 40 00 00    add %al,(%rax) 
    40093d: 00 00     add %al,(%rax) 
    40093f: 00 6a 07    add %ch,0x7(%rdx) 
    400942: 40 00 00    add %al,(%rax) 
    400945: 00 00     add %al,(%rax) 
    400947: 00 71 07    add %dh,0x7(%rcx) 
    40094a: 40 00 00    add %al,(%rax) 
    40094d: 00 00     add %al,(%rax) 
    40094f: 00 78 07    add %bh,0x7(%rax) 
    400952: 40 00 00    add %al,(%rax) 
    400955: 00 00     add %al,(%rax) 

在這一點上我有什麼,我看着有點想法。大概用400753行,我們跳到這張表的某個地方,但是什麼?或者我的理解完全失效了?

+0

在.rodata中是0x400928嗎?如果它只是在.text部分,與代碼混合在一起,那很奇怪。通常情況下,出於性能原因,將數據和代碼分開編組,因爲CPU具有拆分緩存(以及單獨的dTLB/iTLB)。 –

+0

它是在.rodata – nichow

+0

好的,所以你必須使用'-D'或其他東西來反彙編非代碼。現在您知道爲什麼您的工具不想爲您反彙編:P –

回答

3

跳轉表是指針的數組,而不是代碼。反彙編器並不知道,所以它將字節解碼爲指令。你必須忽略,只是看個字節:

400928: 55      push %rbp 
400929: 07      (bad) 
40092a: 40 00 00    add %al,(%rax) 
40092d: 00 00     add %al,(%rax) 
40092f: 00 5c 07 40    add %bl,0x40(%rdi,%rax,1) 

前8個字節是55 07 40 00 00 00 00 00,一個指針指示在0x400755。那就是你找到case 0的地方。

+0

我們如何知道'case 0'而不是其他數字? – nichow

+1

@nichow:因爲它直接使用'switch()'操作數作爲數組索引,沒有add/sub來抵消它或任何東西。除非您之前沒有在代碼中發生過這種情況。 –