2016-10-26 32 views
1

我是CS學生,學習IA-32程序集。對於一個項目,我們已經獲得了一個程序的可執行文件。我們可以使用objdump等工具來檢查二進制文件,但不允許看到原始的源代碼。該程序接受一個輸入字符串並將其與另一個神祕字符串進行比較。如果兩個字符串都是不是相同,程序會發出警報,並且我放棄了這個任務。這將是一個有趣的任務...如果電訊局長會打擾回答我的問題... Grr ...閱讀IA32彙編代碼 - 確定隱藏的字符串?

所以,如果你不介意給我一些指針,我想問問論壇如果我走在正確的軌道上。當我的代碼可執行文件運行objdump -d CODE,我可以深入看到這個在main()函數:

08048a44 <main>: 
... 
8048af6: e8 d0 08 00 00   call 80493cb <get_string> 
8048afb: 89 04 24    mov %eax,(%esp) 
8048afe: e8 ad 00 00 00   call 8048bb0 <test_string> 

我有理由確信get_string()從用戶獲取一個字符串 - 它可能是一個包裝函數對於fscanf()或其他 - 然後指向該字符串的指針被保存到寄存器%eax。下一行將指針移動到%esp,然後調用test_string()。下面是代碼:

08048bb0 <test_string>: 
8048bb0: 83 ec 1c    sub $0x1c,%esp 
8048bb3: c7 44 24 04 6c a4 04 movl $0x804a46c,0x4(%esp) 
8048bba: 08 
8048bbb: 8b 44 24 20    mov 0x20(%esp),%eax 
8048bbf: 89 04 24    mov %eax,(%esp) 
8048bc2: e8 bd 04 00 00   call 8049084 <cmp_strings> 
8048bc7: 85 c0     test %eax,%eax 
8048bc9: 74 05     je  8048bd0 <test_string+0x20> 
8048bcb: e8 bc 07 00 00   call 804938c <alarm> 
8048bd0: 83 c4 1c    add $0x1c,%esp 
8048bd3: c3      ret  

這就是我認爲正在發生的事情...

08048bb0 <test_string>: 
8048bb0: sub $0x1c,%esp   // Adjusts %esp for new function 
8048bb3: movl $0x804a46c,0x4(%esp) // test_string is stored at $0x804a46c; move that pointer into %esp 
8048bba:        // ??? 
8048bbb: mov 0x20(%esp),%eax  // Moves test_string ptr to %eax 
8048bbf: mov %eax,(%esp)   // Moves test_string ptr to %esp - not sure why...? 
8048bc2: call 8049084 <cmp_strings> // Calls cmp_strings(), probably with %eax and %esp as argument strings 
8048bc7: test %eax,%eax    // %eax is the returned value 
8048bc9: je  8048bd0 <test_string+0x20> // Should we jump to alarm()? 
8048bcb: call 804938c <alarm>  // If we reach here, I flunk 
8048bd0: add $0x1c,%esp   // restores %esp to original value 
8048bd3: ret       // exits 

所以......如果我是對的,線#2是這裏最重要的一個。我懷疑神祕字符串存儲在內存地址$0x804a46c。但我不確定。我還注意到,當我使用字符串工具時,我看到:

[linux]$ strings -t x CODE | grep 46c 
    246c My dog has fleas. 
[linux]$ 

這是有希望的......但不具有說服力。內存地址$0x804a46c不是246c

所以......對於這篇冗長的文章道歉,但人們可以告訴我,如果我在正確的軌道上?任何洞察力或智慧是瘋狂的讚賞!

非常感謝! -RAO

+2

使用'objdump'來查看給定地址處的字符串。 'strings'給你文件偏移量,而不是虛擬地址。當然,如果您再次使用'objdump'查看節標題,那麼也可以翻譯它們。 – Jester

+1

地址爲「8048bba」的「神祕操作碼」只是前面指令的一部分。它可能包含在下一行,因爲指令編碼太長了。請注意,指令中的值是'0x804a46c','6c''a4'和'04'全部列在前一行。 – davmac

+0

@davmac:是的,正好。我通常使用'objdump -drwC'來避免('-w'意思是「寬」,並且將指令的所有字節放在同一行上,而不管列的寬度如何)。 –

回答

3

除非存在一些反調試技巧,否則cmp_strings()只接受兩個參數,這兩個參數都在test_string()內給出。當然,它們都是字符串,第一個字符串取自一個常量位置0x804a46c,而第二個字符串(它的指針,當然不是字符串本身)是test_string()的一個參數。通話前即時堆疊看起來是這樣的:

 |_______________| 
ESP: | <your string> | <-- cmp_strings() 1st arg 
+04: | 0x804a46c | <-- cmp_strings() 2nd arg 
+08: |  ...  | 
+0C: |  ...  | 
+10: |  ...  | 
+14: |  ...  | 
+18: |  ...  | 
+1C: | return adress | <-- ESP at the start of test_string() 
+20: | <your string> | <-- test_string() 1st arg 
+24: |  ...  | 

您可以直接在運行時使用GDB(在一般情況下,有必要檢查«祕密»字符串內容,因爲這裏沒有顯示的代碼可以改寫)。只需break *0x8048bc2,run然後x/sb 0x804a46c

+0

是的,這樣做! x/sb 0x804a46c「我的狗有跳蚤。」完美,謝謝!你也給了我一個GDB x命令的好消息,我預計在不久的將來會使用這個命令。謝謝! – Pete

+0

@Pete:順便說一下,GDB可以比默認情況下更具交互性。使用'gdb --tui',並在啓動時輸入'layout asm'來查看程序集。 – hidefromkgb

2

下一行將指針移至%esp,然後調用test_string()。在eaxesp尋址的存儲器,即

mov %eax,(%esp)存儲值。在堆棧頂部。要將該指針複製到esp中,您必須執行mov %eax, %esp,這不是一個好主意,因爲CPU使用ss:esp作爲堆棧指針。

movl $0x804a46c,0x4(%esp) // test_string is stored at $0x804a46c; move that pointer into %esp

再次 「入esp」 是的是完全錯誤的水平不準確的。這會將值0x804a46c寫入地址esp+4的內存中,所以如果您要從堆棧中獲取值pop,則會彈出第二個值(位於堆棧頂部的右下方)。

mov 0x20(%esp),%eax // Moves test_string ptr to %eax

負載 「輸入字符串的指針」 到eax。這是eax之前的call <test_string>。你可能是這個意思,並寫了錯誤的評論?

mov %eax,(%esp) // Moves test_string ptr to %esp - not sure why...?

將它保存在「棧頂」,所以如果你將開始在這裏流行從堆棧值,你會首先彈出的輸入字符串的指針,然後將該0x804a46c值。查看hidefromkgb堆棧內容的ASCII藝術的答案。

然後,它很可能是call 8049084 <cmp_strings>挑選出棧作爲參數的兩個指針,做一些事情,併爲正確的字符串返回零(因爲任何非零返回值將使未來je失敗,並引發call <alarm>

你或許應該在cmp_strings我們快速瀏覽一下也一樣,看它是否是普通的C類strcmp或者它如何可以返回零。

而作爲小丑指出,它應該能夠objdump也是神祕0x804a46c內容。如果這是早期的任務,它可能會變得更糟使用易於讀取的字符串數據訪問數據部分。

如果這將是更困難的任務,它也可以指向代碼段中的假指令形成一些字符串..或最終甚至不是假指令(儘管產生有意義的asm代碼也形成一些短字符串不是在x86上微不足道......例如,我曾經爲我的256B intros .com文件的開頭添加了「PED」,它只是搞亂了一些堆棧,並未影響我的其他介紹......並且在一次大小的編碼比賽中我用xlat指向代碼,以獲得想要的位模式,在51 bytes中繪製希臘國旗)。

+0

謝謝Ped7g,這是很好的細節。我正在慢慢地學習,雖然IA-32的語法看起來很簡單,但它很難遵循,也很容易被誤解。我已將您的所有評論複製到筆記中。 :) – Pete

+0

@Pete我個人非常喜歡英特爾語法(特別是NASM變種)。但恐怕你不是完全可以自由選擇。雖然objdump可以配置爲產生Intel語法的GNU方言:http://stackoverflow.com/a/10362655/4271923但是請確保它不會在課堂上稍後咬你,當你將被強制執行到AT&T嗎?此外,如果您將此視爲第一次ASM,也許AT&T不會傷害那麼多。 (我在幾個月/年的時間裏學習x86,在其他CPU上編碼,而且英特爾語法看起來很熟悉) – Ped7g

+0

嗯......好的食物。老實說,我是一名IA-32的新手,並且只在兩天前瞭解到objdump。我正在處理擺在我面前的語法,而不是真正理解它來自哪裏。我必須考慮更多。謝謝! – Pete