<em id="pzl9c"></em>
      <dl id="pzl9c"><ins id="pzl9c"></ins></dl>
      <dfn id="pzl9c"></dfn>

        <progress id="pzl9c"></progress>
        <div id="pzl9c"><ol id="pzl9c"></ol></div>
          <div id="pzl9c"><tr id="pzl9c"></tr></div>

          <em id="pzl9c"></em>

            <em id="pzl9c"><ins id="pzl9c"><mark id="pzl9c"></mark></ins></em>
            <dl id="pzl9c"></dl>

            <dl id="pzl9c"></dl>

              <div id="pzl9c"></div>
              <dl id="pzl9c"><ins id="pzl9c"></ins></dl>

              <dfn id="pzl9c"></dfn>
              <sup id="pzl9c"><ins id="pzl9c"></ins></sup>

                <dl id="pzl9c"></dl>

                飄云閣(PYG官方論壇)

                 找回密碼
                 加入論壇

                QQ登錄

                只需一步,快速開始

                掃一掃,訪問微社區

                查看: 3098|回復: 36
                打印 上一主題 下一主題

                [原創] 談談vmp的還原(3)

                [復制鏈接]
              1. TA的每日心情
                擦汗
                2016-4-19 21:35
              2. 簽到天數: 3 天

                [LV.2]偶爾看看I

                跳轉到指定樓層
                樓主
                發表于 2018-4-14 19:24:16 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
                本帖最后由 wai1216 于 2018-4-15 18:25 編輯

                0x00 前言
                寫在5.4之前

                vs2010,代碼放在了github:vmp

                0x01 寄存器
                先說context
                init初始化context分兩種情況

                那么第二種,就是隨機生成了

                關于pushad pushfd的保存

                如何選取空閑的context
                代碼如下:
                1. int n = 0, k = 0;
                2. char cpu[16] = {0};

                3. int _getContextIndex( int type)
                4. {
                5.         if( tpye - 1 >= 2)
                6.         {
                7.                 switch(type)
                8.                 {
                9.                         case 0:
                10.                         case 4:
                11.                                 return dis->reg[0];
                12.                         case 1:
                13.                         case 5:
                14.                                 return dis->reg[1];
                15.                         case 2:
                16.                         case 6:
                17.                                 return dis->reg[2];
                18.                         case 3:
                19.                         case 7:
                20.                                 return dis->reg[3];                        
                21.                         case 9:
                22.                         case 0xD:
                23.                                 return dis->reg[9];               
                24.                         default:
                25.                                 return 0;                                                                                                
                26.                 }
                27.         }
                28.         else
                29.         {
                30.                 switch(type)
                31.                 {
                32.                 case 0:
                33.                 case 1:
                34.                 case 2:
                35.                 case 3:
                36.                 case 5:
                37.                 case 6:
                38.                 case 7:
                39.                 case 8:
                40.                 case 9:
                41.                 case 0xa:
                42.                         return dis->reg[_type];
                43.                 case 4:
                44.                         return -1;
                45.                 default:
                46.                         return 0;
                47.                 }
                48.         }
                49. }

                50. for( int i = 0; i < 16; i++)
                51. {
                52.         if( dis->reg[i] < 0xff)
                53.         {
                54.                         cpu[ dis->reg[i]] = 1;
                55.         }
                56. }
                57. i = 0;
                58. while( cpu[i] || rand()%2 != 1)
                59. {
                60.         i++;
                61.         return _getContextIndex(tpye);
                62. }
                63. dis->reg[k] = n;
                64. return _getContextIndex(tpye);
                復制代碼
                這里說下,看到這部分實現的時候,腦子里的想法是當成樹結構,用dfs去識別判斷,因為以為是真輪轉。記得,還給校長說,加密與解密那個目錄處理的方法好像是圖算法。
                再注意到a2/v13 == 2, 才會去get context, 隨意看一個調用

                關系到lval
                那么其他的情況在只是return context,那么就好辦了,因為可以得到,并不是真輪轉

                0x10 變形
                下面這個東西,也是我最佩服vmp作者的地方,因為就這點東西,就可以做很多事情了。


                首先這個函數,我也不知道怎么命名好,所以就當成fixed吧,可能叫plasmodium比較好

                1. _BOOL1 __fastcall CHECK_POP_ESP_OR_CONTEXT(struct_esi *a1)
                2. {
                3.   return a1->_var1_vm_interpreter_mnemonic == 2
                4.       && a1->_var2_addressing_mode == 2
                5.       && (!a1->_var3_lval_type_byte_word_dword_or_vm_displacement || a1->_reg_index != 4);
                6. }

                7. _BOOL1 __fastcall Check_PUSH_ESP_OR_CONTEXT(struct_esi *a1, char a2, char a3)
                8. {
                9.   return a1->_var1_vm_interpreter_mnemonic == 1
                10.       && a1->_var2_addressing_mode == 2
                11.       && a2 == a1->_var3_lval_type_byte_word_dword_or_vm_displacement
                12.       && a3 == a1->_reg_index;
                13. }

                14. _BOOL1 __fastcall CHECK_POP_AX(struct_esi *a1)
                15. {
                16.   return a1->_var1_vm_interpreter_mnemonic == 2 && a1->_var2_addressing_mode == 1;
                17. }

                18. //函數倒敘判斷
                19. _BOOL1 __usercall [email protected]<al>(int *[email protected]<eax>, char [email protected]<dl>, int a3)
                20. {
                21.   bool _ret = 0;

                22.   if ( *_index >= 2 )
                23.   {
                24.     _cur_index = *_index;
                25.     _struct_cur = getStruct_1(*(a3 - 4), *_index);
                26.         //判斷當前vm_mnemonic是否為0x4,0xf6
                27.     if ( _struct_cur->_var1_vm_interpreter_mnemonic != 4
                28.                 && _struct_cur->_var1_vm_interpreter_mnemonic != 0xF6
                29.                 || _struct_cur->_var3_lval_type_byte_word_dword_or_vm_displacement != __var3_lval_type_byte_word_dword_or_vm_displacement )// ?
                30.     {
                31.                 //為其他mnemonic 高于0x2e
                32.       if ( _struct_cur->_var1_vm_interpreter_mnemonic  >= 0x2A )
                33.       {
                34.         if ( CHECK_POP_ESP_OR_CONTEXT(_struct_cur) && getlen(*(a3 - 4)) - 1 > _cur_index )
                35.         {
                36.           if ( Check_PUSH_ESP_OR_CONTEXT(_struct_next,_struct_cur->_var3_lval_type_byte_word_dword_or_vm_displacement,_struct_cur->_reg_index)
                37.                                 && System::__linkproc__ RandInt(2) == 1 )
                38.           {
                39.             _struct_next->_reg_index = 4;
                40.             _struct_next->_var3_lval_type_byte_word_dword_or_vm_displacement = 2;
                41.             _struct_next->_other |= 4u;
                42.             _struct_new = (*(**(a3 - 4) + 16))();
                43.             _struct_new->_var1_vm_interpreter_mnemonic = 1;
                44.             _struct_new->_var2_addressing_mode = 3;
                45.             _struct_new->_var4_index = 3;
                46.             _struct_new->_var3_lval_type_byte_word_dword_or_vm_displacement = _struct_cur->_var3_lval_type_byte_word_dword_or_vm_displacement;
                47.             _struct_new->_other |= 4u;
                48.             _mov_var2_to_var3(*(a3 - 4), _struct_new, _struct_cur);
                49.             _mov_var2_to_var3(*(a3 - 4), _final, _struct_new);// add_to_list
                50.           }
                51.         }
                52.         else if ( CHECK_POP_AX(_struct_cur) )          // _fix var2 == 2 && var3 == 1
                53.         {
                54.           _next = _cur_index + 1;
                55.           _size = getlen(*(a3 - 4)) - 1;
                56.                   __ = __OFSUB__(_size,_next);
                57.           _len = _size - _next;
                58.           if ( !((_len < 0) ^ __) )
                59.           {
                60.             _pos = _len + 1;
                61.             _next = _next;
                62.             do
                63.             {
                64.               _struct_next = getStruct_1(*(a3 - 4), _next);
                65.               if ( !CHECK_POP_ESP_OR_CONTEXT(_struct_next)
                66.                                   || CHECK_POP_ESP(_struct_next)
                67.                                   || _struct_next->_var3_lval_type_byte_word_dword_or_vm_displacement != _struct_cur->_var3_lval_type_byte_word_dword_or_vm_displacement )
                68.               {
                69.                 break;
                70.               }
                71.               if ( System::__linkproc__ RandInt(2) == 1 )
                72.               {
                73.                 _struct_cur->_var2_addressing_mode = 2;
                74.                 _struct_cur->_reg_index = _struct_next->_reg_index;
                75.                 _struct_cur->_other |= 4u;
                76.                 return _ret;
                77.               }
                78.               ++_next;
                79.               --_pos;
                80.             }
                81.             while ( _pos );
                82.           }
                83.         }
                84.       }//0x1d之前 basic....
                85.       else if ( _struct_cur->_var3_lval_type_byte_word_dword_or_vm_displacement == __var3_lval_type_byte_word_dword_or_vm_displacement )//?
                86.       {
                87.         _struct_prev_prev = getStruct_1(*(a3 - 4), _cur_index - 2);
                88.         _struct_prev = getStruct_1(*(a3 - 4), _cur_index - 1);
                89.         if ( CHECK_LODSW_PUSH_AX(_struct_prev_prev, 1) && CHECK_LODS_PUSH_CONTEXT(_struct_prev, __var3_lval_type_byte_word_dword_or_vm_displacement) )
                90.         {
                91.           _cur_index -= 2;//移動到_prev_prev,指針
                92.           if ( !_struct_prev_prev->_rand_switch && !_struct_prev->_rand_switch )
                93.           {
                94.             _ret = !(_cur->_other & 1) && !CHECK_POP_ESP(_struct_prev);
                95.           }
                96.         }
                97.       }
                98.     }
                99.     else
                100.     {
                101.       _struct_prev_prev = getStruct_1(*(a3 - 4), _cur_index - 2);
                102.       _struct_prev = getStruct_1(*(a3 - 4), _cur_index - 1);
                103.       if ( CHECK_LODS_PUSH_CONTEXT(_struct_prev_prev, __var3_lval_type_byte_word_dword_or_vm_displacement) && CHECK_LODS_PUSH_CONTEXT(_struct_prev, __var3_lval_type_byte_word_dword_or_vm_displacement) )
                104.       {
                105.         _cur_index -= 2;
                106.         if ( _struct_prev_prev->_rand_switch || _struct_prev->_rand_switch || System::__linkproc__ RandInt(2) != 1 )
                107.         {
                108.           v10 = !CHECK_POP_ESP(_struct_prev_prev) && !CHECK_POP_ESP(_struct_prev);
                109.           _ret = v10;
                110.         }
                111.         else
                112.         {
                113.           if ( CHECK_POP_ESP(_struct_prev_prev) )
                114.           {
                115.             if ( _struct_prev->_var2_addressing_mode == 1 )
                116.               *_struct_prev->_Displacement_Immediate += 4;
                117.           }
                118.           else if ( CHECK_POP_ESP(_struct_prev) )
                119.           {
                120.             if ( _struct_prev_prev->_var2_addressing_mode == 1 )
                121.               *_struct_prev_prev->_Displacement_Immediate -= 4;
                122.           }
                123.           else
                124.           {
                125.             _ret = 1;
                126.           }
                127.           if ( _struct_prev->_var2_addressing_mode != 2
                128.             || _struct_prev_prev->_var2_addressing_mode != 2
                129.             || _struct_prev_prev->_reg_index != _struct_prev->_reg_index )
                130.           {
                131.             _struct_prev_prev->_other |= 4u;
                132.             _struct_prev->_other |= 4u;
                133.             _ExchangePos(*(a3 - 4), _struct_prev, _struct_prev_prev);// 交換當前的前兩個
                134.           }
                135.           else
                136.           {
                137.             _struct_prev->_reg_index = 4;            // fix
                138.             _struct_prev->_var3_lval_type_byte_word_dword_or_vm_displacement = 2;
                139.             _struct_prev->_other |= 4u;
                140.             _struct_new = (*(**(a3 - 4) + 16))();
                141.             _struct_new->_var1_vm_interpreter_mnemonic = 1;// push [imm]...
                142.             _struct_new->_var2_addressing_mode = 3;
                143.             _struct_new->_var4_index = 3;
                144.             _struct_new->_var3_lval_type_byte_word_dword_or_vm_displacement = _first->_var3_lval_type_byte_word_dword_or_vm_displacement;
                145.             _struct_new->_other |= 4u;
                146.             _mov_var2_to_var3(*(a3 - 4), _struct_end, _struct_cur);
                147.           }
                148.         }
                149.       }
                150.       else
                151.       {
                152.         if ( CHECK_LODS_PUSH_CONTEXT(_struct_prev, __var3_lval_type_byte_word_dword_or_vm_displacement) )
                153.         {
                154.           --_cur;//指針-1
                155.           if ( CHECK_POP_ESP(_struct_prev) )
                156.             return _ret;
                157.           _prev = _cur - 1;
                158.           if ( Vmp_Fixed(&_prev, __var3_lval_type_byte_word_dword_or_vm_displacement, a3) == 0 )// 遞歸調用,這時候就體現出第3個的用處了
                159.             return _ret;
                160.           *v3 = _prev;
                161.           _prev = _prev;
                162.           _ret = 1;
                163.         }
                164.         else
                165.         {
                166.           _prev = _cur - 1;
                167.           if ( Vmp_Fixed(&_prev, __var3_lval_type_byte_word_dword_or_vm_displacement, a3) )
                168.           {
                169.             _index = _prev;
                170.             _struct_prev_prev = getStruct_1(*(a3 - 4), _prev - 1);
                171.             _struct_prev = getStruct_1(*(a3 - 4), _prev);
                172.             if ( CHECK_LODS_PUSH_CONTEXT(_struct_prev_prev, __var3_lval_type_byte_word_dword_or_vm_displacement) )
                173.             {
                174.               --_cur;
                175.               if ( CHECK_POP_ESP(_struct_prev_prev) )
                176.                 return _ret;
                177.               _prev__ = _cur;
                178.               _ret = 1;
                179.             }
                180.             else
                181.             {
                182.               _prev = *v3 - 1;
                183.               if ( Vmp_Fixed(&_prev, __var3_lval_type_byte_word_dword_or_vm_displacement, a3) )
                184.               {
                185.                 *v3 = _prev;
                186.                 _prev = _prev;
                187.                 _ret = 1;
                188.               }
                189.             }
                190.           }
                191.         }
                192.         if ( _ret != 0 && rand()%2 == 1 )
                193.         {
                194.           _prev_index = _retn_index(_struct_prev);
                195.           _cur_index = _retn_index(_cur);
                196.           _flag = _prev - _prev_index == _prev_index - _cur_index;// len
                197.           if ( _prev__ - _prev_index == _prev_index - _cur_index && _cur_index - 1 >= _prev_index )
                198.           {
                199.             int dis = _cur_index - _prev_index;
                200.             while ( 1 )
                201.             {
                202.               _success = sub_48AF88(_prev_index, _prev_index + _prev__ - _prev_index, v13, a3);// 直到找到不同的
                203.               v13 = v16;
                204.               if ( !v15 )
                205.                 break;
                206.               ++v38;
                207.               if ( !--v14 )
                208.                 goto LABEL_45;
                209.             }
                210.             _flag = 0;
                211.           }
                212. LABEL_45:
                213.           if ( _flag != 0 )
                214.           {
                215.             _struct_prev = getStruct_1(*(a3 - 4), _prev_index);
                216.             _struct_prev->_var1_vm_interpreter_mnemonic = 1;
                217.             _struct_prev->_var2_addressing_mode = 2;
                218.             _struct_prev->_reg_index = 4;
                219.             _struct_prev->_var3_lval_type_byte_word_dword_or_vm_displacement = 2;
                220.             _struct_prev->_other |= 4u;
                221.             _struct_cur = getStruct_1(*(a3 - 4), _prev_index + 1);
                222.             _struct_cur->_var1_vm_interpreter_mnemonic = 1;
                223.             _struct_cur->_var2_addressing_mode = 3;
                224.             _struct_cur->_var4_index = 3;
                225.             _struct_cur->_var3_lval_type_byte_word_dword_or_vm_displacement = __var3_lval_type_byte_word_dword_or_vm_displacement;
                226.             _struct_cur->_other |= 4u;
                227.             if ( _prev_index + 2 <= _cur_index - 1 )
                228.             {
                229.               v19 = _prev_index + 2 - _cur_index;
                230.               _prev_index = _cur_index - 1;
                231.               do
                232.               {
                233.                 (*(**(a3 - 4) + 12))(*(a3 - 4), v39--);
                234.                 ++v19;
                235.               }
                236.               while ( v19 );
                237.             }
                238.           }
                239.           else
                240.           {
                241.             if ( _cur_index - 1 >= _prev_index )
                242.             {
                243.               v20 = _cur_index - _prev_index;
                244.               v40 = _prev_index;
                245.               do
                246.               {
                247.                 v21 = getStruct_1(*(a3 - 4), v40);
                248.                 v21->_other |= 4u;
                249.                 ++v40;
                250.                 --v20;
                251.               }
                252.               while ( v20 );
                253.             }
                254.             if ( _cur_index - 1 >= _prev_index )
                255.             {
                256.               v22 = _cur_index - _prev_index;
                257.               v41 = _prev_index;
                258.               do
                259.               {
                260.                 sub_47FB0C(*(a3 - 4), v41, v41 + _prev__ - _prev_index);//exchange
                261.                 ++v41;
                262.                 --v22;
                263.               }
                264.               while ( v22 );
                265.             }
                266.           }
                267.         }
                268.       }
                269.       if ( _ret )
                270.         _ret = (_cur->_other & 1) == 0;
                271.     }
                272.   }
                273.   return _ret;
                274. }
                復制代碼
                當我看到這里的時候,真的,如果不是語言不在同一個頻道,可能就膜拜了。
                隨意的,舉個例子。這里可能會需要一些數據結構的知識
                注意是倒敘進行判斷的

                記當前結構為一個_cur_node
                記當前上一個節點為_prev_node
                記當前下一個節點為_next_node

                假定
                1. _cur_node: LODS BYTE PTR DS:[ESI]  POP DWORD PTR DS:[EDI+EAX*4]
                2. _next_node: LODS BYTE PTR DS:[ESI] PUSH DWORD PTR DS:[EDI+EAX*4]
                復制代碼
                這兩條在操作什么,很明顯,可以看出vmp不是沒有一些組合的
                那么可能會出現下面的情況
                _next_node變成PUSH ESP
                new node,生成一個新的節點,記為_tmp_node
                1. _tmp_node: POP EAX PUSH DWORD PTR ES:[EAX]
                復制代碼
                之后在插入
                Before:
                1. LODS BYTE PTRDS:[ESI]  POP DWORD PTR DS:[EDI+EAX*4]
                2. LODS BYTE PTR DS:[ESI]  PUSH DWORD PTR DS:[EDI+EAX*4]
                復制代碼
                After:
                1. LODS BYTE PTRDS:[ESI]  POP DWORD PTR DS:[EDI+EAX*4]
                2. PUSH ESP
                3. POP EAX PUSH DWORDPTR ES:[EAX]
                復制代碼

                注意到eax一致,然后明白這個函數了嗎?
                好像就這些了,我大概想闡述的東西,就這些。
                0x11 說下我還原的思路
                在我逆的過程中,一直在猜想vmp作者的構造思路。
                最開始的時候,我的想法是把esi看成vmp_encodes,那么asm有套opcode的構造手冊,vmp作者也應該有一套這樣的手冊,當然也不是說像intel手冊那種。但我一直從各個角度去思考,都想不出,vmp作者是怎么構造出這些精彩的東西的。有興趣的,可以嘗試一下,如果是大一大二,我可能就這樣繼續下去了
                之后我想既然知道了規則,可能不同版本,會有一些變化,但大致框架如此。
                而不同的是,我所想的是,是還原為encodes,而不是asm,這點也重要,因為即使trace,或者使用插件,是的,你人工可能可以識別,那么代碼認識么,當然可以寫成分析樹或寫個虛擬引擎自己跑,但我想,這也是vmp作者愿意看到的情況
                那么既然想還原成encodes,先解析esi,之后只要規則到位,那么我們可以得到disp,imm,sib,modrm,prefix。還需要確認的,就只剩下opcode了,所幸的是,相同mnemonic所對應的opcode并不多,就大致解決了類型不對等的情況了。

                本帖被以下淘專輯推薦:

                分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友 微信微信
                收藏收藏8 轉播轉播 分享分享 分享淘帖2 頂 踩 友情贊助 微信分享
              3. TA的每日心情
                無聊
                2018-7-6 21:46
              4. 簽到天數: 165 天

                [LV.7]常住居民III

                沙發
                發表于 2018-4-15 00:02:56 | 只看該作者
                感謝,羨慕在學校就已這么厲害了  
                ps:另外冒昧能問一下在哪所大學 ?這么厲害 。
                回復 支持 反對

                使用道具 舉報

              5. TA的每日心情
                開心
                2018-6-24 22:00
              6. 簽到天數: 13 天

                [LV.3]偶爾看看II

                板凳
                發表于 2018-4-21 13:51:38 | 只看該作者
                又免費學了一課,也感謝樓主費心寫這么多話出來
                回復 支持 反對

                使用道具 舉報

              7. TA的每日心情
                開心
                2018-4-21 14:13
              8. 簽到天數: 1 天

                [LV.1]初來乍到

                報紙
                發表于 2018-4-21 14:15:50 | 只看該作者
                很棒,謝謝分享
                回復 支持 反對

                使用道具 舉報

                該用戶從未簽到

                地板
                發表于 2018-4-23 20:14:51 | 只看該作者
                學習下,表示沒看懂
                回復 支持 反對

                使用道具 舉報

              9. TA的每日心情
                開心
                2018-5-3 21:43
              10. 簽到天數: 3 天

                [LV.2]偶爾看看I

                7#
                發表于 2018-5-2 11:02:06 | 只看該作者
                菜鳥表示看不懂,依然感謝
                回復 支持 反對

                使用道具 舉報

              11. TA的每日心情
                開心
                2018-8-3 20:31
              12. 簽到天數: 3 天

                [LV.2]偶爾看看I

                8#
                發表于 2018-5-8 18:28:34 | 只看該作者
                非常感謝分享,給力
                回復 支持 反對

                使用道具 舉報

              13. TA的每日心情
                開心
                2018-9-23 07:46
              14. 簽到天數: 18 天

                [LV.4]偶爾看看III

                9#
                發表于 2018-5-8 20:30:44 | 只看該作者
                膜拜下大牛 支持!
                回復 支持 反對

                使用道具 舉報

              15. TA的每日心情

                2018-6-16 05:03
              16. 簽到天數: 23 天

                [LV.4]偶爾看看III

                10#
                發表于 2018-5-8 22:26:28 | 只看該作者
                這應該是博士生科研用的,我們幼兒園小朋友完全看不懂。
                回復 支持 反對

                使用道具 舉報

                您需要登錄后才可以回帖 登錄 | 加入論壇

                本版積分規則

                關閉

                站長推薦上一條 /1 下一條

                快速回復 返回頂部 返回列表
                11选5中奖报道