IDA動態除錯解RC4

山西小嫦娥發表於2024-05-02

IDA動態除錯解RC4

本篇部落格所有內容,均學習於無名俠大佬在bilibili的影片:https://www.bilibili.com/video/BV1WQ4y1X7TY

LazyIDA熊貓版:https://github.com/P4nda0s/LazyIDA

實驗檔案下載:https://github.com/P4nda0s/SycRevLearn


有一些演算法的加密與解密是相同的演算法過程,例如 RC4、部分簡單的異或演算法等。

測試方法:

1.設定演算法輸入資料A

2.獲取演算法輸出資料B

3.設定演算法輸入資料為B (上一步結果代入)

4.獲取演算法輸出資料 B',對比 B' 與 A 的值,若相等則該演算法加密解密是同一段程式碼。

通俗來講,就是輸入A輸出B,輸入B輸出A。

拿影片中的題目來分析:

  sub_85F057(v14);//反除錯
  puts("Welcome!! give me your flag:\n");
  do
  {
    v8 = j_j_j___fgetchar();
    if ( v8 == 10 )
      break;
    input[index++] = v8;
  }
  while ( (int)index < 44 );
  if ( index >= 0x200 )
    j____report_rangecheckfailure();
  input[index] = 0;
  len = j__strlen(input);
  sub_85CEFB((int)v13, (int)v14, len);
  for ( i = 0; i < 256; ++i )
    v12[i] = v13[i];
  fun1((int)v13, (int)input, len);//加密函式
  for ( j = 0; j < 44; ++j )
  {
    if ( v7[j] == input[j] )
      ++v10;
  }
  if ( v10 == 44 )
    puts("Yes, u right!\n");
  else
    puts("no no no\n");
  system("pause");
  return 0;
}

啥也不要分析,主要看fun1((int)v13, (int)input, len);

input是我們輸入的,這個函式會將我們的input進行加密。

  for ( j = 0; j < 44; ++j )
  {
    if ( v7[j] == input[j] )
      ++v10;
  }

然後在透過這裡進行比較。

根據for語句可以得知,flag的長度可能是44,這裡為什麼說是可能呢,如果是逐位元組加密,就是我們輸入的每一個字元加密後都是一個字元,那麼flag的長度肯定是44,如果我們的輸入,一個字元加密成了兩個字元,那麼我們輸入的flag的長度就是22,因為這裡並不確定,所以只能猜測是44。

程式有反除錯,我嘗試將反除錯給nop掉,但是發現反除錯似乎又與加密程式碼有著一定的關係,我嘗試了,沒能理清楚反除錯和加密程式碼的關係,所以這裡和影片中的一樣,還是帶著反除錯來分析,這裡用IDA附加執行中的程式就行,因為已經執行完反除錯的那句程式碼了。

測試是否加密與解密是相同的演算法

在加密函式處斷下

image-20240502223047670

先輸入:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

檢視input的值

image-20240502222926791

再F8單步步過,檢視此時加密後的input

image-20240502223302203

用外掛將資料提取出來

image-20240502225423609

[+] Dump 0xCFF1BC - 0xCFF1E8 (44 bytes) :
D62DE6F797244F2EA92DDDA37904C885B9E4E8D90B325F9908C07B804E134AC497DA7562D0AD31C558C3BBF6

可以看到我們輸入的44個a被加密成了上述資料

這次我們將上述資料進行輸入,看執行之後是否可以還原成44個a

上述資料存在不可見字元,不能從命令框裡直接輸入,這裡需要用到Paste Data來改棧上的資料。

這次我們先輸入41個b

image-20240502231707435

透過Paste Data將資料改成D62DE6F797244F2EA92DDDA37904C885B9E4E8D90B325F9908C07B804E134AC497DA7562D0AD31C558C3BBF6

image-20240502231739109

再F8單步步過,檢視此時加密後的input

image-20240502231816745

可以看到資料恢復成了41個a

  fun1((int)v13, (int)input, len);//加密函式
  for ( j = 0; j < 44; ++j )
  {
    if ( v7[j] == input[j] )
      ++v10;
  }
  if ( v10 == 44 )
    puts("Yes, u right!\n");
  else
    puts("no no no\n");
  system("pause");

再回頭看一下程式,程式是將v7和input進行比較,v7其實就是flag加密之後的形式,我們此時只要將v7dump下來,把v7的資料當作input進行傳入,經過加密函式之後就可以得到flag了。

v7:

[+] Dump 0x7DF5F0 - 0x7DF61C (44 bytes) :
E415C4EDA62F5610BB13EBAD7556C7BBBBE9B9CC023A509F369069BE7C4244CAC6D4245CD2B924C11893B3EA

再一次執行程式

image-20240502232226350

將input用Paste Data改成E415C4EDA62F5610BB13EBAD7556C7BBBBE9B9CC023A509F369069BE7C4244CAC6D4245CD2B924C11893B3EA

image-20240502232319008

再F8單步步過,檢視此時加密後的input

image-20240502232348326

可以看到flag已經被還原了,按一下鍵盤上的A鍵就能轉成字串形式方便複製

SYC{Pjx_s_Wom3n_cl0thing_1s_S0oo0o0_cute!1i}

今天就先這樣,等明天我試著做一下其它題目,看是否學到了精髓。

2024年5月2日23點28分


相關文章