網站首頁 編程語言 正文
前言
這次的題目可以練習到循環加結構體數組和ifelse的大量嵌套。
逆向這種東西就是一個經驗的積累,做得多了就會有感覺,這次的分析我會詳細寫一下如何判斷哪里是if哪里是while這種邏輯判斷。
題目描述
給你一個鏈表的頭節點 head
和一個整數 val
,請你刪除鏈表中所有滿足 Node.val == val
的節點,并返回 新的頭節點 。
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] ?? ??? ??? ??? ?//下面是業務代碼
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,這里可以看出來應該是一個while或者if
004E35AF ?je ? ? ? ? ?removeElements+0A8h (4E3628h) //跳出while
004E35B1 ?mov ? ? ? ? eax,dword ptr [cur] ?? ??? ?
004E35B4 ?mov ? ? ? ? ecx,dword ptr [eax] ?? ??? ?//熟悉的取指針的內容
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)] //這里應該是調用了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)] ?? ?//這里應該是調用了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的結尾
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 ? ? ? ? ? ? ?
分析
- 根據004E35AB行代碼可以看出這里是一個if或者while
- 再看他跳到的004E3628的上一行是跳回到判斷所以可以判斷這一個大while
- 一步一步看下去會看到004E35B6這一行發現是一個if判斷再看一下他判斷失敗時跳的位置
- 失敗會跳到004E3617看他的上一行代碼004E3615 jmp removeElements+0A6h (4E3626h)
- 可以看出來判斷就跳到下面的代碼!=就順序執行然后跳過的代碼并出循環
- 繼續看匯編代碼會看到好幾個這樣的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;//更新頭結點 free(cur);//釋放存放val的節點 cur = head;//更新當前節點 } //中間刪 else{ prev->next = cur->next;//鏈接 free(cur);//釋放當前為val的節點 cur = prev->next;//更新當前節點 } } //不是val就往后遍歷 else{ prev = cur; cur = cur->next; } } return head; }
原文鏈接:https://blog.csdn.net/qq_43147121/article/details/128068597
相關推薦
- 2022-11-03 Python?文檔解析lxml庫的使用詳解_python
- 2022-09-06 Go?語言選擇器實例教程_Golang
- 2024-03-08 SpringBoot項目多模塊開發詳解
- 2022-10-08 Golang?Web?框架Iris安裝部署_Golang
- 2022-07-04 C#操作Windows服務類System.ServiceProcess.ServiceBase_C#
- 2022-04-04 Error running : No valid Maven installation found.
- 2022-02-17 npm run serve Syntax Error: Error: Node Sass versi
- 2024-03-07 SpringAOP對獲取Bean的影響理解
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支