最近在讀《python 灰帽子》一書,按照書上代碼照抄一邊,運(yùn)行結(jié)果卻是預(yù)期的效果,前三章的練習(xí)通過網(wǎng)上搜索修改后可以正常運(yùn)行。第四章的第一個示例代碼printf_random的結(jié)果也和書上不一致(可能是因為書上系統(tǒng)環(huán)境是32位,我的是64位吧)。錯誤結(jié)果如下圖:

網(wǎng)上查了一下,找到這篇文章:
http://www.docin.com/p-680357401.html。
里面通過在回調(diào)方法
printf_randomizer方法中調(diào)用dbg.dump_context()方法查看context內(nèi)容。發(fā)現(xiàn)
parameter_addr = dbg.context.Esp + 0x8 處 0x8 改為 0x4??梢匀〉蕉?heap)上的字符串“Loop iteration 4!”, 然后截取字符串替換字符串的方式實現(xiàn)了預(yù)期結(jié)果。但是文章最后也提到了這種方式最后修改的并不是存放counter的那塊內(nèi)存中的值,只是修改了最后輸出語句中兩個字節(jié)的值。
另外還發(fā)現(xiàn)另一篇文章http://blog.csdn.net/u012763794/article/details/52174275。
里面提到發(fā)現(xiàn)調(diào)用的軌跡:
call python27.PyOS_snprintf ----> msvcr90._vsnprintf --> msvcr90.printf
而參數(shù)入棧在_vsnprintf 就已經(jīng)搞定了,到后面的printf直接壓字符串入棧就可以了,應(yīng)該msvcrt也是一樣的。
所以在printf打斷點時就只能修改字符串了,想要修改counter,需要在_vsnprintf調(diào)用之前加斷點,在嘗試msvcr90._vsnprintf 和 msvcr90.printf失敗后,最終作者python27.PyOS_snprintf成功了,但是作者文章中寫的比較模糊,最后成功的代碼也沒貼出來,我試了幾次也沒成功。
在查看dump_context時發(fā)現(xiàn)EDI里放的好像就是counter里的值!
然后通過修改context.Edi最終也成功出來結(jié)果。
但是也存在回調(diào)函數(shù)調(diào)用兩次的情況,和文章的情況不一樣的地方是他輸出的是一個固定的常量地址(難道是counter的地址?),而我的輸出的是counter的原始值。
最后貼出代碼:
print_random


