日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++逆向分析移除鏈表元素實現方法詳解_C 語言

作者:ch132 ? 更新時間: 2022-12-26 編程語言

前言

這次的題目可以練習到循環加結構體數組和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

欄目分類
最近更新