C++逆向分析移除鏈表元素實現(xiàn)方法詳解
前言
這次的題目可以練習(xí)到循環(huán)加結(jié)構(gòu)體數(shù)組和ifelse的大量嵌套。
逆向這種東西就是一個經(jīng)驗的積累,做得多了就會有感覺,這次的分析我會詳細寫一下如何判斷哪里是if哪里是while這種邏輯判斷。
題目描述
給你一個鏈表的頭節(jié)點 head
和一個整數(shù) val
,請你刪除鏈表中所有滿足 Node.val == val
的節(jié)點,并返回 新的頭節(jié)點 。
debug版匯編代碼
004E3580 push ebp
004E3581 mov ebp,esp
004E3583 sub esp,0D8h
004E3589 push ebx
004E358A push esi
004E358B push edi
004E358C lea edi,[ebp-0D8h]
004E3592 mov ecx,36h
004E3597 mov eax,0CCCCCCCCh
004E359C rep stos dword ptr es:[edi] //下面是業(yè)務(wù)代碼
004E359E mov eax,dword ptr [head]
004E35A1 mov dword ptr [cur],eax //cur = head;
004E35A4 mov dword ptr [prev],0 //prev = 0;
004E35AB cmp dword ptr [cur],0 //cur != 0,這里可以看出來應(yīng)該是一個while或者if
004E35AF je removeElements+0A8h (4E3628h) //跳出while
004E35B1 mov eax,dword ptr [cur]
004E35B4 mov ecx,dword ptr [eax] //熟悉的取指針的內(nèi)容
004E35B6 cmp ecx,dword ptr [val] //這是判斷if(cur.filed1 == val)
004E35B9 jne removeElements+97h (4E3617h) //跳到else
004E35BB mov eax,dword ptr [cur]
004E35BE cmp eax,dword ptr [head] //if(cur==head),同上這又是個ifelse
004E35C1 jne removeElements+6Ah (4E35EAh)
004E35C3 mov eax,dword ptr [cur]
004E35C6 mov ecx,dword ptr [eax+4] //ecx = cur->field2
004E35C9 mov dword ptr [head],ecx //head = cur->field2
004E35CC mov esi,esp
004E35CE mov eax,dword ptr [cur]
004E35D1 push eax
004E35D2 call dword ptr [__imp__free (4E834Ch)] //這里應(yīng)該是調(diào)用了free
004E35D8 add esp,4
004E35DB cmp esi,esp
004E35DD call @ILT+335(__RTC_CheckEsp) (4E1154h)
004E35E2 mov eax,dword ptr [head] //eax = head
004E35E5 mov dword ptr [cur],eax //cur = head
004E35E8 jmp removeElements+95h (4E3615h)
004E35EA mov eax,dword ptr [prev] //這里是else
004E35ED mov ecx,dword ptr [cur] //ecx = cur,eax = prev
004E35F0 mov edx,dword ptr [ecx+4] //edx = cur.field2
004E35F3 mov dword ptr [eax+4],edx //prev.field2 = cur.field2
004E35F6 mov esi,esp
004E35F8 mov eax,dword ptr [cur]
004E35FB push eax
004E35FC call dword ptr [__imp__free (4E834Ch)] //這里應(yīng)該是調(diào)用了free
004E3602 add esp,4
004E3605 cmp esi,esp
004E3607 call @ILT+335(__RTC_CheckEsp) (4E1154h)
004E360C mov eax,dword ptr [prev]
004E360F mov ecx,dword ptr [eax+4]
004E3612 mov dword ptr [cur],ecx //cur = prev->field2
004E3615 jmp removeElements+0A6h (4E3626h) //從這里可以看出來是一個if~else
004E3617 mov eax,dword ptr [cur]
004E361A mov dword ptr [prev],eax //prev = cur
004E361D mov eax,dword ptr [cur]
004E3620 mov ecx,dword ptr [eax+4] //cur.field2
004E3623 mov dword ptr [cur],ecx /cur = cur.filed2
004E3626 jmp removeElements+2Bh (4E35ABh) //這里是while的結(jié)尾
004E3628 mov eax,dword ptr [head] //出了while
004E362B pop edi
004E362C pop esi
004E362D pop ebx
004E362E add esp,0D8h
004E3634 cmp ebp,esp
004E3636 call @ILT+335(__RTC_CheckEsp) (4E1154h)
004E363B mov esp,ebp
004E363D pop ebp
004E363E ret
分析
- 根據(jù)004E35AB行代碼可以看出這里是一個if或者while
- 再看他跳到的004E3628的上一行是跳回到判斷所以可以判斷這一個大while
- 一步一步看下去會看到004E35B6這一行發(fā)現(xiàn)是一個if判斷再看一下他判斷失敗時跳的位置
- 失敗會跳到004E3617看他的上一行代碼004E3615 jmp removeElements+0A6h (4E3626h)
- 可以看出來判斷就跳到下面的代碼!=就順序執(zhí)行然后跳過的代碼并出循環(huán)
- 繼續(xù)看匯編代碼會看到好幾個這樣的if~else
struct tmp{ DWORD val; DWORD tmpAddr; }; struct tmp* func(DWORD head,DWORD val) { cur = head; prev = 0; while(cur != 0){ if(cur->filed1 == val){ if(cur==head){ head = cur->field2; free(cur); cur = head; }else{ prev->field2 = cur->field2; free(cur); cur = prev->field2; } }else{ prev = cur; cur = cur->field2; } } return head; }
源代碼
* struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* cur = head, *prev = NULL; while(cur){ if(cur->val == val){ //頭刪 if(cur == head){ head = cur->next;//更新頭結(jié)點 free(cur);//釋放存放val的節(jié)點 cur = head;//更新當(dāng)前節(jié)點 } //中間刪 else{ prev->next = cur->next;//鏈接 free(cur);//釋放當(dāng)前為val的節(jié)點 cur = prev->next;//更新當(dāng)前節(jié)點 } } //不是val就往后遍歷 else{ prev = cur; cur = cur->next; } } return head; }
到此這篇關(guān)于C++逆向分析移除鏈表元素實現(xiàn)方法詳解的文章就介紹到這了,更多相關(guān)C++移除鏈表元素內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++?判斷計算機存儲器字節(jié)序(端序)的幾種方式
字節(jié)序是計算機存儲數(shù)據(jù)的格式,主存儲器(主存)的字節(jié)序?qū)Τ绦虻囊浦残院图嫒菪灾陵P(guān)重要,利用聯(lián)合體、指針、位移和掩碼等方法可以檢測和處理字節(jié)序問題,對于內(nèi)存數(shù)據(jù)操作重要,也關(guān)系到跨平臺和網(wǎng)絡(luò)通信的數(shù)據(jù)處理2024-10-10C語言實現(xiàn)兩個遞減數(shù)列中尋找某一個數(shù)
這篇文章主要介紹了C語言實現(xiàn)兩個遞減數(shù)列中尋找某一個數(shù),是一類經(jīng)典的數(shù)組操作算法,需要的朋友可以參考下2014-09-09C 標(biāo)準(zhǔn)I/O庫的粗略實現(xiàn)教程
下面小編就為大家分享一篇C 標(biāo)準(zhǔn)I/O庫的粗略實現(xiàn)教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12C++11系列學(xué)習(xí)之可調(diào)用對象包裝器和綁定器
這篇文章主要介紹了C++11系列學(xué)習(xí)之可調(diào)用對象包裝器和綁定器,下文基于C++的相關(guān)資料展開詳細內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-04-04vs code 配置c/c++環(huán)境的詳細教程(推薦)
這篇文章主要介紹了vs code 配置c/c++環(huán)境的詳細教程(推薦),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11C++中char*轉(zhuǎn)換為LPCWSTR的解決方案
最近在學(xué)習(xí)C++,遇到了一個char*轉(zhuǎn)換為LPCWSTR的問題,通過查找資料終于解決了,所以下面這篇文章主要介紹了C++中char*轉(zhuǎn)LPCWSTR的解決方案,文中通過詳細的示例代碼介紹的很詳細,有需要的朋友可以參考借鑒,下面來一起看看吧。2017-01-01