2015-04-25 46 views
1

我們在計算機建築學教授給我們,詢問密碼的示例程序。任務是在比較輸入的密碼並決定是否正確後更改跳轉操作碼。 我寫了一個程序,它可以在給定的二進制文件的特定位置更改任何字節。獲取二進制文件中的特定操作碼的準確位置

這裏的pasword程序的代碼:

int main(int argc, char* argv[]){ 
    char *pw = "12441233"; 
    char pass[32]; 

    printf("Enter password:\n"); 

    scanf("%s", pass); 

    if(strncmp(pass,pw,8)) 
    { 
     printf("Password wrong\n"); 
     exit(-1); 
    } 
    printf("Welcome\n"); 
} 

所以我在控制檯中輸入$ objdump -d task和得到這個:

...

400703:|| 48 8b 5d e8 || MOV -0x18(%RBP),%RBX

400707:|| 64 48 33 1c 25 28 00 || XOR%FS:0×28,%RBX

40070e:|| 00 00

400710:|| 74 05 || JE 400717

400712:|| e8 29 fe ff ff || callq 400540 < __stack_chk_fail @ PLT>

400717:|| 48 83 c4 58 ||加$將0x58,%RSP

40071b:|| 5b ||流行%RBX

...

74JE我想更改爲75JNE字節。 我怎樣才能讓我的74字節的確切位置在相應的二進制文件,這樣我可以把它改成一個新的價值?

+0

在內存中的位置已經很少做在文件中的位置。你知道74 05之前和之後的字節值。搜索這些文件。 –

+0

我知道內存地址與它無關,這就是爲什麼我問我還應該做些什麼。我需要它用於我的更改程序,它看起來像這樣:changebyte -d POSITION BYTE OLDFILE NEWFILE。我想我通過二進制編輯器搜索功能找到了相應的字節,但對於所需的解決方案,我需要一個可重複的wy來查找二進制文件中的位置。 – Max

+0

這是linux還是windows?我可以給你一個Windows可執行文件的答案。 – Pyjong

回答

1

正如漢斯指出,存儲位置無關,用它做。你需要做的是找到字節(或字節)在文件中的位置。爲此,一個非常好的反彙編程序(這將是IDA-Pro)讓您的生活變得非常簡單。可悲的是,IDA的價格曲線陡峭,所以我們會堅持使用您可以輕鬆獲得的工具。

接下來是一臺Linux機器上完成,使用gcc版本4.8.2和gdb 7.7上運行的Ubuntu 14.04

  1. 編譯使用gcc -g -ansi -pedantic -Wall的代碼。不是一個真正的問題,但main應該有一個返回值。

  2. 程序裝載到GDB,把一個破發點,在主,然後運行該程序。當我打的破發點,我用gdb的disass命令來獲取反彙編列表如下圖所示:

    (gdb) disass 
        Dump of assembler code for function main: 
        0x000000000040067d <+0>:  push %rbp 
        0x000000000040067e <+1>:  mov %rsp,%rbp 
        0x0000000000400681 <+4>:  push %rbx 
        0x0000000000400682 <+5>:  sub $0x58,%rsp 
        0x0000000000400686 <+9>:  mov %edi,-0x54(%rbp) 
        0x0000000000400689 <+12>: mov %rsi,-0x60(%rbp) 
    => 0x000000000040068d <+16>: mov %fs:0x28,%rax 
        0x0000000000400696 <+25>: mov %rax,-0x18(%rbp) 
        0x000000000040069a <+29>: xor %eax,%eax 
         [ ... ] 
        0x00000000004006cc <+79>: mov $0x8,%edx 
        0x00000000004006d1 <+84>: mov %rcx,%rsi 
        0x00000000004006d4 <+87>: mov %rax,%rdi 
        0x00000000004006d7 <+90>: callq 0x400520 <[email protected]> 
        0x00000000004006dc <+95>: test %eax,%eax 
        0x00000000004006de <+97>: je  0x4006f4 <main+119> 
        0x00000000004006e0 <+99>: mov $0x4007c0,%edi 
        0x00000000004006e5 <+104>: callq 0x400530 <[email protected]> 
         [ ... ] 
        0x0000000000400718 <+155>: retq 
        End of assembler dump. 
    
  3. 漂亮不祥的期待,我知道,但花一秒鐘環顧四周,注意到一些事情; a。在角括號中的數字(即 < 97>)得到該指令是從功能的開始位於的字節數。在你的情況下,你需要的操作碼是從函數開始的97個字節。 b。前9個字節(前四個指令)通常看起來就像我們這裏的內容,它們是函數的序言,它們爲函數設置激活(或堆棧)框架。

  4. 現在,我們需要找到主要是在你的可執行文件。這往往是OS和編譯器特定的。在我的情況下,一臺Linux主機上的工作,我知道這些代碼存儲在文件的的.text部分,我可以使用該工具readelf得到那個位置,如下圖所示;

    readelf --wide -S task 
    There are 35 section headers, starting at offset 0x1478: 
    
    Section Headers: 
        [Nr] Name    Type   Address   Off Size ES Flg Lk Inf Al 
        [ 0]     NULL   0000000000000000 000000 000000 00  0 0 0 
        [ 1] .interp   PROGBITS  0000000000400238 000238 00001c 00 A 0 0 1 
        [ 2] .note.ABI-tag  NOTE   0000000000400254 000254 000020 00 A 0 0 4 
        [ 3] .note.gnu.build-id NOTE   0000000000400274 000274 000024 00 A 0 0 4 
        [ 4] .gnu.hash   GNU_HASH  0000000000400298 000298 00001c 00 A 5 0 8 
        [ 5] .dynsym   DYNSYM   00000000004002b8 0002b8 0000c0 18 
          [ .... ] 
        [13] .text    PROGBITS  0000000000400590 000590 000202 00 AX 0 0 16 
        [14] .fini    PROGBITS  0000000000400794 000794 000009 00 AX 0 0 4 
        [15] .rodata   PROGBITS  00000000004007a0 0007a0 000037 00 
    Key to Flags: 
        W (write), A (alloc), X (execute), M (merge), S (strings), l (large) 
        I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
        O (extra OS processing required) o (OS specific), p (processor specific) 
    
  5. 根據上述內容,我們可以看到,的.text部分將在0x400590的存儲器位置和0x400792結束位置(基於尺寸爲0x202)開始。此外,我們可以看到0x590文件中的的.text部分已經偏移。回首我們的拆解,我們可以看到,main開始在0x0040067d,這是的.text(仔細的檢查)的範圍內。

  6. 我們現在擁有的應用程序(的.text段的起始內存地址的入口點,如果我們從入口點減去main的起點,我們應該得到偏移量(以。存儲器),用於main相對於在碼被映射最後添加該值來在可執行代碼的偏移應該給我們的main文件位置:

    000067d: 5548 89e5 5348 83ec 5889 7dac 4889 75a0 UH..SH..X.}.H.u. 
    000068d: 6448 8b04 2528 0000 0048 8945 e831 c048 dH..%(...H.E.1.H 
    000069d: c745 b8a4 0740 00bf ad07 4000 e882 feff [email protected]@..... 
    00006ad: ff48 8d45 c048 89c6 bfbd 0740 00b8 0000 [email protected] 
    00006bd: 0000 e8ac feff ff48 8b4d b848 8d45 c0ba .......H.M.H.E.. 
    00006cd: 0800 0000 4889 ce48 89c7 e844 feff ff85 ....H..H...D.... 
    00006dd: c074 14bf c007 4000 e846 feff ffbf ffff [email protected] 
    00006ed: ffff e88c feff ffbf cf07 4000 e832 feff [email protected] 
    00006fd: ff48 8b5d e864 4833 1c25 2800 0000 7405 .H.].dH3.%(...t. 
    000070d: e82e feff ff48 83c4 585b 5d    .....H..X[] 
    
  7. 作爲快速完整性檢查,還記得我提到,從主拆卸的主要的前幾個字節是相當鍋爐板,如果我們看一下它們,並將它們組裝成我們的機器,我們得到:

    push %rbp    0x55 
        mov %rsp,%rbp  0x48 0x89 0xe5 
        push %rbx    0x53 
        sub $0x58,%rsp  0x48 0x83 0xec 0x58 
        mov %edi,-0x54(%rbp) 0x89 0x7d 0xac 
    
  8. 鑑於上面的字節序列與步驟5中的字節請求序列匹配,這是一個相當安全的假設,我們已經找到main在可執行文件中的位置。現在所要做的就是將偏移量爲0x6de的字節從0x74修改爲0x73。

N.B.國際開發協會確實有一個免費版本,並有一些限制,所以它是值得你花時間來抓住它並玩它。

希望這有助於, 牛逼

+0

非常感謝,這對我很重要。再次感謝非常好的消除。 – Max

0

使用readelf工具,並尋找LOAD程序頭。他們給的地址objdump之間的映射出你(VirtAddr,又名p_vaddr),並在文件中的偏移量(PhysAddr,又名p_paddr)。