《轉》運算子巧妙原理解析

2022-03-31 08:44:40 字數 2366 閱讀 2195

最近一直研究乙個對個人而言很有價值的乙個lib庫的逆向。在今天下班後突然靈感閃現,這個斷斷續續逆了接近一周的核心管理類。終於在今天給逆完了。在最後乙個函式裡,碰到了之前基本沒有用過的一條指令。(呵呵,高手見笑了!)當然光看單句的彙編指令,是沒有辦法看出具體的作用的,而且還很可能會認為原作者本來就是用彙編來實現的!呵呵,先不廢話,先貼出反彙編**一睹為快:

mov        dword ptr,64h   // int b

xor         eax,eax

cmp        dword ptr,0

setg        al   

sub         eax,1

and         eax,64h

add         eax,0c8h

mov         dword ptr [a],eax   // int a

今天的lib裡面的那段迷惑的**就跟這段**一致,唯獨a、b變數不一樣。當然這個不影響結果。一開始可能會對setg這條指令的用途不了解。二是看下面藍色的三條指令,什麼又是減,又是and,又是add一些莫名奇妙的立即數。還真讓人迷惑這段**翻譯成c++將怎麼寫。難道就一句一句的翻譯?這樣的話恐怕一條彙編就是一句c++。而且到了setg這條指令時還真不知道怎麼單獨的將其翻譯成c++的什麼語句。呵呵!這可能也就是逆向所帶來的樂趣之一吧(個人觀點)!

好了。不廢話,先分析下。首先b是乙個變數,首先被賦值成0x64(100)。然後將b與0進行比較,如果有心的朋友會覺得奇怪,這個cmp的下面一條語句怎麼不是跳轉語句,一般都是比較後,然後根據比較結果進行跳轉。否則cmp有什麼意義呢?到這裡的話誤導我們的就是setg這條指令了。要了解它,首先得知道cmp會影響到標誌暫存器的標誌位。cmp是執行的減法操作,將前面的運算元減去後面的運算元。與sub的區別就是它不將減後的值放到目的運算元中。所以cmp有可能減溢位等,從而影響到了標誌位。由此一來我們就算猜測都能知道setg應該與標誌位有關係。然後通過資料或者奔騰x86指令集查詢表(我使用的平台是intel x86 cpu)。就可以知道setg指令乃是大於零為真,setg al 就是如果cmp比較後大於零,al裡的值將是0x01。setg的判斷表示式就是(zf=0 and sf=of),還有個setle( zf = 1 or sf <> of ),等等還有幾個,這裡就不一一說明。有興趣的朋友可以去查閱。

之後藍色的三條指令,仔細分析會發現,如果eax為0的話,sub eax, 1後eax將是0xffffffff。之後再and eax, 64h結果eax為64h,之後再是加c8h。之後就給a變數了。然後再分析另外一種情況,假如eax為1, sub eax, 1後將是0,再and等於沒運算,之後才是加上c8h,後面就一樣了。前面的xor eax, eax就不說了,就是把eax清零。這樣一分析,可以有個大概的c++語句的錐形。那就是三目運算子:(?:)。

好了,這句c++語句很短,那就是:

int b = 100;

int a = ( b <= 0 ) ? 300 : 200;

哈哈,很簡單吧!其實逆向就是這樣,分析一大段很可能翻譯過來的c++**就一句而已。這篇文章說是巧妙原理解析。這裡的巧妙之處就在於編譯器很聰明(ms很厲害),這些細節的技巧可以給我們很多的啟發。這個三目運算在彙編層面上,首先編譯器會把後面冒號兩邊的數字求差,差將用於and運算。b <= 100後eax要麼為1要麼為0。因此後面的sub eax, 1後eax要麼為0xffffffff,要麼為0,為0xffffffff表示b小於等於0。b小於等於0之後的and eax, 64h也就將300 - 200的差100賦值給了eax,之後再add c8h(200),便得到了300。反之,sub eax, 1後。 eax將為0。and運算後等於就沒有算上差值,之後加上冒號後面的數。就是小的200了。呵呵!這些細節,ms的程式很細心啊!

還有就是一點,這裡記錄的差值是有符號的,而且是固定的冒號前面的數減去後面的數。如果前面的數小於後面的數,那麼這裡記錄的將是乙個負值,原理一樣。

再舉乙個例子吧:

mov         dword ptr,1

xor         eax,eax

cmp         dword ptr,0

setg        al   

lea         eax,[eax+eax-1]

mov         dword ptr [a],eax

這個例子就不用說了,直接貼c++**:

int b = 1;

int a = ( b > 0 )? 1 : -1;

或者是bool型別的。注意看紅色指令的巧用,它直接代替了and和add指令。大家慢慢體會!   

如果後面冒號兩邊任意一邊是變數的話,就不會被編譯成這樣子了,就會被編譯成普通的跳轉類似於if語句了。

好了,這裡就是一點小小的心得,當是長個記性。

運算子巧妙原理解析

最近一直研究乙個對個人而言很有價值的乙個lib庫的逆向。在今天下班後突然靈感閃現,這個斷斷續續逆了接近一周的核心管理類。終於在今天給逆完了。在最後乙個函式裡,碰到了之前基本沒有用過的一條指令。呵呵,高手見笑了!當然光看單句的彙編指令,是沒有辦法看出具體的作用的,而且還很可能會認為原作者本來就是用彙編...

C C 條件(三目)運算子巧妙原理解析

最近一直研究乙個對個人而言很有價值的乙個lib庫的逆向。在今天下班後突然靈感閃現,這個斷斷續續逆了接近一周的核心管理類。終於在今天給逆完了。在最後乙個函式裡,碰到了之前基本沒有用過的一條指令。呵呵,高手見笑了!當然光看單句的彙編指令,是沒有辦法看出具體的作用的,而且還很可能會認為原作者本來就是用彙編...

運算子的巧妙應用

我的github and,按位與。以 a b為例,將 a和 b轉化為二進位制後,都為1的位設為1。程式 a 6 b 3 var dump a b 輸出 int 2 原理 提醒操作 郵箱簡訊 文章被收藏 開關按鈕 開關按鈕 開關按鈕 被關注開關按鈕 開關按鈕 開關按鈕 開關按鈕 開關按鈕 開關按鈕 1...