Rervese.kr題解 Assassin菜逼之路

Easy Crack

很久不做題了,就當是練手了,很簡單的題目,首先查看字符串看到

這裏寫圖片描述

關鍵詞很少了,很明確,然後再看一下判斷條件貌似就一個
這裏寫圖片描述

很容易就可以組合最終結果是

Ea5yR3versing

Easy Keygen

運行一下程序,發現需要輸入一個Name然後輸入一個什麼註冊碼,要求Name輸入和註冊碼對應,註冊碼要求是5B134977135E7D13,估計是一個簡單的算法吧。
進入一看發現就是個簡單的抑或…

這裏寫圖片描述

簡單寫一個小程序

# -*- coding: utf-8 -*-  
import pymssql
target = [0x5b,0x13,0x49,0x77,0x13,0x5e,0x7d,0x13]
#target = '5B134977135E7D13'
flag = ''
for i in range(len(target)):
    if i%3==0:
        flag += chr(target[i]^16)
    elif i%3==1:
        flag += chr(target[i]^32)
    elif i%3==2:
        flag += chr(target[i]^48)
print flag

得到答案是K3yg3nm3

Easy Unpack

下載文件之後查看ReadME發現需要找到入口地址OEP,說實話之前都沒怎麼接觸過脫殼的內容,在網上照葫蘆畫瓢試了試,顯示簡單所謂的不分析的單步跟蹤法,具體的思路如下:

  1、用OD載入待脫殼文件,如果出現壓縮提示,選擇“不分析代碼”;
  2、向下單步跟蹤,實現向下的跳轉;
  3、遇到程序往上跳轉的時候(包括循環),在回跳的下一句代碼上單擊並按鍵盤上的“F4”鍵跳過回跳指令;
  4、OD中的灰色線條表示跳轉沒有實理,不必理會,紅色線條表示跳轉已經實現;
  5、如果剛載入程序的時候,在附近有一個CALL指令,那麼就要按鍵盤上的“F7”鍵跟進這個CALL內,不然程序很容易運行起來(這個在這裏貌似沒什麼體現);
  6、在跟蹤的時候,如果執行某個CALL指令後就運行,一定要按鍵盤上的“F7”鍵進入這個CALL之內再單步跟蹤(這個也沒什麼體現,我直接都是F8搞定的);
  7、遇到在popad指令下的遠轉移指令時,要格處注意,因爲這個遠轉移指令的目的地很可能就是OEP。

跟着上面的步驟,主要就是F8和F4一會兒就有一個長距離條轉

這裏寫圖片描述

之後就來到了我們熟悉的函數位置(單步法具體爲什麼也不是很懂)
這裏寫圖片描述

那麼答案就是00401150嘍。

但是我覺得了解一下其他的脫殼方法還是非常非常有必要的。我這裏就直接收藏啦,原文地址在這裏
https://www.52pojie.cn/thread-259984-1-1.html
內容如下

===============================================================    

     一、單步跟蹤法
  脫殼的方法有很多,先來講脫殼方法中最基礎的單步跟蹤法。單步跟蹤法就是利用OD的單條指令執行功能,從殼的入口一直執行到OEP,最終通過這個OEP將原程序dump出來。然當,在單步跟蹤的時候需要跳過一些不能執行到的指令。
  使用單步跟蹤法追蹤OEP的常見步驟:
  1、用OD載入待脫殼文件,如果出現壓縮提示,選擇“不分析代碼”;
  2、向下單步跟蹤,實現向下的跳轉;
  3、遇到程序往上跳轉的時候(包括循環),在回跳的下一句代碼上單擊並按鍵盤上的“F4”鍵跳過回跳指令;
  4、OD中的綠色線條表示跳轉沒有實理,不必理會,紅色線條表示跳轉已經實現;
  5、如果剛載入程序的時候,在附近有一個CALL指令,那麼就要按鍵盤上的“F7”鍵跟進這個CALL內,不然程序很容易運行起來;
  6、在跟蹤的時候,如果執行某個CALL指令後就運行,一定要按鍵盤上的“F7”鍵進入這個CALL之內再單步跟蹤;
  7、遇到在popad指令下的遠轉移指令時,要格處注意,因爲這個遠轉移指令的目的地很可能就是OEP。
=============================================================== 
  二、ESP定律法
  ESP定律法是脫殼的利器,是國外友人發現的。有了ESP定律,可以方便我們脫掉大多數的壓縮殼。可謂是本世紀破解界中最偉大的發現之一。這裏只簡單的看一下狹義ESP定律的原理。
  使用ESP定律追蹤OEP的常見步驟:
  1、將待脫殼程序載入到OD中,開始就按鍵盤上的“F8”鍵單步跟蹤一步,這時如果看到OD右邊的寄存器窗口中的ESP寄存器的值有沒有變爲紅色,如果發現ESP寄存器的值變爲紅色,執行第2步;
  2、在OD的命令行窗口中執行命令hrXXXXXXXX,xxxxxxxx就是變爲紅色的ESP寄存器的值,在輸入命令之後,一定不要忘記按鍵盤上的回車鍵;
  3、按鍵盤上的“F9”鍵讓程序運行起來;
  4、使用單步跟蹤的方法跟蹤到OEP即可。
=============================================================== 
  三、二次斷點法
  二次斷點是有技巧的下兩個斷點,在兩個斷點之後就可以很輕鬆的找到OEP。
  使用二次斷點法追蹤OEP的常見步驟:
  1、將待脫殼程序載入到OD中,單擊OD的“選項”菜單下的“調試設置”命令,在彈出的“調試選項”對話框中切換到“異常”選項卡,勾選該選項卡下的所有複選框,也就是忽略所有異常;
  2、按鍵盤上的“ALT+M”組合鍵打開OD的內存窗口;
  3、在OD的內存窗口中找到“.rsrc”區段,單擊該區段後按鍵盤上的“F2”鍵在該區段上下一斷點;
  4、按“Shift+F9”讓程序運行到斷點心處,而後再次打開OD的內存窗口,這次在“.rsrc”區段上面的“.code”區段(有的時候就是“.text”)上下一個斷點;
  5、按“shift+F9”讓程序運行到第二次下的斷點處,然後單步跟蹤既可以來到OEP。
=============================================================== 
  四、末次異常法
  在脫殼方法中,末次異常法又被稱爲最後一次異常法,這是最基礎的脫殼技術之一。末次異常法脫殼很是簡單,但就是這簡單的脫殼方法可以挑掉曾經風靡一時的強殼。
  使用末次異常法追蹤OEP的常見步驟:
  1、將待脫殼程序載入到OD中,單擊OD的“選項”菜單,在彈出的菜單中單擊“調試設置”命令,在隨後彈出的“調試選項”對話框中切換到“異常”選項卡,清除該選項卡下所有複選框,也就是不忽略任何異常;
  2、連續按鍵盤上的“Shift+F9”組合鍵讓程序運行起來,記錄按鍵的次數X;
  3、回到OD中,按鍵盤上的“Ctrl+F2”組合鍵重新載入程序,按X-1次“Shift+F9”組合鍵;
  4、在OD右下角窗口中找到“SE句柄”或是“SE處理程序”,記錄此處的內存地址;
  5、在OD的反彙編窗口中跟隨到上一步記錄下的內存地址,並在此內存地址處下一個斷點;
  6、按鍵盤上的“Shift+F9”組合鍵讓程序運行到上一步下的斷點處,按鍵盤上的“F2”鍵取消此處的斷點;
  7、使用單步跟蹤法追蹤到OEP。
=============================================================== 
  五、模擬跟蹤法
  在這章中講到的衆多脫殼方法中,我們首先講了單步跟蹤法脫殼,因爲單步跟蹤脫殼法是脫殼技術中最基礎的方法,在後面其它的一些脫殼方法中總會或多或少的配合單步跟蹤法才能順利完成脫殼工作。便是始終是一次次的按“F8”鍵來單步跟蹤程序,偶爾遇到回跳就跳過執行,這樣機械性的操作很是煩人,那麼能不能讓機器來代替人力,讓工具幫我們單步跟蹤呢?答案是肯定的,這也就是這節講的內容——模擬跟蹤法。模擬脫殼法就是模擬單步跟蹤來進行查找OEP。
  模擬跟蹤法的常見步驟:
  1、將待脫殼程序載入OD中,先簡單的跟蹤一下程序,看看有沒有SEH暗樁;
  2、按鍵盤上的“ALT+F9”打開OD的內存窗口,找到“SFX,輸入表,資源”的行,並記錄此行的內存地址;
  3、在OD的命令行窗口執行命令“tc   eip<上一步中記錄下的地址”,命令執行後就會跟蹤到OEP。
=============================================================== 
  六、SFX自動脫殼法
  在上一節,我們使用模擬跟蹤法代替手動單步跟蹤法進行脫殼。在OD中,不但可以利用模擬跟蹤來代替單步跟蹤進行脫殼,從而節省勞動力,還有一種SFX自動脫殼的方法也可以節省勞動力,並能快速有效的將程序的殼脫掉。
  使用SFX自動脫殼法脫殼的常見步驟:
  1、將OD設置爲忽略所有異常;
  2、在OD的“調試選項”對話框的“SFX”選項卡中選擇“字節模式跟蹤實際入口”選項並確定;
  3、將待脫殼程序載入OD,待程序載入完成後,會直接停在OEP處。
=============================================================== 
  七、出口標誌法
  前面幾個脫殼方法中有一個共同點,就是在單步跟蹤到popad指令後面不遠處的jmp指令的時候,就可以大膽的判斷這個jmp指令的目的地址就是OEP。原因很簡單,popad指令用於將殼運行之前保存的環境恢復,使原程序能正常運行。有些殼的popad指令很少,我們就可以查看被這種殼加殼的程序的所有popad指令,找到後面存在jmp指令的popad指令,然後來到其後的jmp指令的目的地址,這很可能就是OEP,然後就可以進行dump脫殼了。
  使用出口標誌法脫殼的常見步驟:
  1、將待脫殼程序載入OD中,在OD的反彙編客人口中單擊鼠標右鍵,在彈出的右鍵菜單中單擊“查找”→“所有命令”,在彈出的輸入框中輸入“popad”並按“查找”按鈕;
  2、逐一嘗試跟蹤查找到的所有“popad”指令,最終達到程序的OEP。
=============================================================== 
  八、使用脫殼腳本輔助脫殼
  在脫殼的時候,使用模擬跟蹤法可以讓OD代替我們單步跟蹤程序直到OEP,這樣大大提高了脫殼的效率。但是模擬跟蹤法並不能跟蹤到一些較強的殼的OEP,這時我們可以使用高手們寫的脫殼腳本來幫助我們完成脫殼工作,使用脫殼腳本來脫殼要比手動跟蹤方便得多。脫殼腳本就是高手們爲了方便自己或他人脫殼,把自己手動脫殼的步驟記錄下來,保存的一個文本文檔。雖然脫殼腳本是一個文本文檔,可以使用記事本將其打開,但是輕易不要用這種方式修改脫殼腳本,因爲直接修改脫殼腳本,很可能造成脫殼腳本不能正確完成對應的脫殼工作。
=============================================================== 
  九、使用脫殼工具脫殼
  脫殼工具很多,這裏只介紹最爲實用的全自動脫殼機——超級巡警脫殼工具。
  超級巡警脫殼工具的工作方法:
  超級巡警脫殼工具會自動偵測待脫殼程序所加的殼頭,從而判斷出帶脫殼程序是用哪種殼程序加殼的。如果超級巡警脫殼工具支持對該殼的脫殼,就可以很方便的將程序的殼脫掉;如果不支持對該殼的脫殼,則會給我們一個簡單明瞭的提示。
如恆大所說新手儘量使用脫殼機脫殼。
===============================================================

這個題目嘗試了一下別的方法,但是貌似沒成功啊.可能不切合實際情況吧,其他方法其實就是在單步調試法的基礎上的改進吧。

Music Player

首先用IDA打開發現不知道是啥,明顯是加殼過的東西,然後掃描一下發現是這個

這裏寫圖片描述

一開始不知道是什麼東西,從網上查找一下資料發現是一個VB程序吧,之前確實沒怎麼接觸過這個,然後就下載了一個VB.Decompiler.Pro.v9.2雖然版本老了一點但是夠用了.打開之後發現是VB腳本,還是比較清楚的函數,但是由於不是很懂VB的語法,分析沒什麼思路,就去學習了一下大佬的思路了。
首先看到,當音樂盒到了一分鐘的時候可以看到會有一個彈窗
這裏寫圖片描述

然後大牛們的思路是找到VB函數中的彈窗函數,本來應該是MsgBox,但是貌似全稱是rtcMsgBox
這裏還是列舉一下VB程序一般情況下反彙編一般用什麼函數,看這裏
http://blog.csdn.net/programmingring/article/details/38374715
那麼怎麼下斷點呢?一開始頭疼了半天,這麼多程序怎麼找…結果人家在LCG版本都寫好了…
這裏寫圖片描述

然後我們就來到了彈窗的位置,這個一定是經過判斷,不符合要求的一分鐘之後彈出的窗口,那麼比較的位置應該在之前的位置,而且不會太遠,一直在這個函數結束之前總共出現了幾次比較,一類基本上是函數調用之後,不像是時間比較,然而這個就很像是匹配1分鐘了
這裏寫圖片描述

0xea60==60000,這也太巧了,而且我們看到是jl指令,如果出現小於情況才跳轉,在斷點這裏箭頭是灰的,跳轉的位置在彈窗函數之後,很像是如果沒到時間跳過去繼續,如果到點了在這裏繼續執行彈窗。我們只要將jl改爲jmp
然後保存運行,發現過了一分鐘之後音樂還可以繼續播放,但是莫名報錯了!
這裏寫圖片描述

然後就需要找到彈窗的位置了嗯!雖然不知道改怎麼辦,但是我們隱約可以猜到,之前隨着時間移動的時間戳,超過了1分鐘是不是沒法往後移動了???估計就是一個調用時間戳的位置不對了吧(完全是猜測的…後面驗證並不是…)
然後學習一波大佬的思路,既然程序崩潰了,那麼在kernel32.RaiseException位置下斷點,之後再調用堆棧中可以看到出問題的函數(快捷鍵Alt+K)
這裏寫圖片描述

我這裏kernel32.RaiseException位置是72a10dc9
然後我們看一下問題函數吧
這裏寫圖片描述

就是問題函數是這個,那麼我們每次都跳過就好了。
這裏寫圖片描述

呼,太艱難了,自己真菜,題目還是很不錯的~(而且最後也沒有弄明白,爲啥標籤就變了…懶得看了…)

Replace

發現真是一道題都沒法自己獨立完成了…
首先顯示看看有殼沒,索性沒有

這裏寫圖片描述

IDA打開看一下關鍵點,發現可以找到什麼Correct,過去一看再是這個東西….
這裏寫圖片描述

DialogFunc就是一個主函數的功能嘛,但是下面那一坨是啥玩意…沒頭緒看一下OD,發現Correct,然後根據Correct的位置和跳轉的流程可以斷點到輸入數字Check之後,起始在這裏
這裏寫圖片描述

不說別的一直單步下去,發現在一個地方崩潰了???WTF
這裏寫圖片描述

但是爲什麼崩潰呢?我們不開別的什麼流程,我們看一下這句是要用ds段eax值最爲地址,但是這個時候eax值是啥…
這裏寫圖片描述

雖然不知道這個是怎麼生成的,但是這個也太大了!(事實上這麼大的值不就是來自於上面的額…見下圖吧)
這裏寫圖片描述

然後我們只要改一下一個合適的位置先跳過去再說,然後走到後面就牛逼了,修改了源程序了..最後程序變成了這樣,總覺的很像是防靜態的一種手段,看看後面具體想要幹什麼吧
這裏寫圖片描述

然後我們千辛萬苦跳回去了…發現在修改Correct之前還有一個jmp…正好把我們想要的函數跳過。
這裏寫圖片描述

那麼,這個題目到底要幹嘛!!!現在突然靈光一現!我們輸入的是一個10進制數字把!然後我們看本題的第二張圖裏,明顯這裏就是輸入的位置
這裏寫圖片描述

我們記住這個位置是4084D0,然後我們再回到崩潰的位置之前看一下,eax的來源就是來自輸入數字加上一個數字(這個程序之前我們改變過了記得不,我們已經變成了上上上張圖那樣)
我們輸入的數字首先經歷了+1,然後跳出函數之後再+1
這裏寫圖片描述

之後我們跳轉到了這裏!
這裏寫圖片描述

明顯這個是那個db 81擾亂了程序的翻譯,那麼我們看一下從404674一直到40467中間是什麼指令!翻譯一下
這裏寫圖片描述

這就精彩了,就是再我們儲存輸入的位置又加上了0x601605C7
還沒完,後面還在+1+1
這裏寫圖片描述

然後回到了40106啊,至此這個40466f函數才完成,總結一下,計算方法是
輸入值+2+0x601605C7+2

之後程序恢復了40466f打那個90 nop的功能,然後還是到了打兩個nop的程序,再說我們到了Correct之前有一個jmp,好了我們這次的目標就是讓這個nop把那個jmp打掉!

這裏寫圖片描述

目標地址是0x401071我們計算出上面的溢出點在哪即可,注意要用到溢出嗯
這裏寫圖片描述

可能比較亂啊,不過確實是一道好題!自己真菜!

ImagePrc

這個題目一看就是很明確了,界面是一個類似畫板的東西,可以網上畫圖案,然後點擊check,估計就是文件中存着一個圖片,然後和你畫的匹配一下這樣子。然後反編譯一下看代碼

這裏寫圖片描述

然後很容易我們就看到前面是處理圖片的,然後圖片的頭大小是40,然後
這裏寫圖片描述

然後上面這個東西包含着圖片的長和寬,這玩意很重要哇,在後面比較的時候我們注意到大小是90000,所以長寬很重要,雖然我們現在看不到,但是這個實可以在調試過程中看的到的。然後通過調試我們知道高是150,那麼對應的寬就是600了,然後我們簡單判斷一下,匹配的內容一定實在文件的數據段中,所有我們dump這個東西,找到了位置應該是0x47e060,而且計算一下90000大小就是到了0x493ff0,恰巧到這裏也就結束了。然後我不太會dump,然後用OLLYDB的複製到文件弄得…形式如下

這裏寫圖片描述

當然了,這個是非常笨的方法…然後寫了個腳本跑一個圖片出來

#_*_coding:utf-8_*_
import hashlib
from PIL import Image  
file_path = r'dump.txt'
content = open(file_path,'r').readlines()
a = []
for ooo in content:
    sss = ooo.replace('\n','')
    sss = sss.split(' ')
    for i in sss:
        if i =='FF' or i == '00':
            a.append(i)
print len(a)
img=Image.new('RGB',(150,600),(255,255,255))
loding = img.load()
sum=0
for x in range(0,150):
    for y in range(0,600):
        if a[sum]=='FF':
            loding[x,y]=(0,0,0)
        else:
            loding[x,y]=(255,255,255)
        sum+=1
        if sum>90000:
            break
img.show()

然後得到圖片,旋轉一下

這裏寫圖片描述

最終得到答案…但是反映了我不會dump數據…我的天..補課補課…

當然這個資源可以用其他的工具提取,比如eXeScope啊,然後還有一種寫法(這個的輸入dump是bin文件啊)

#_*_coding:utf-8_*_
import hashlib
from PIL import Image  
file_path = r'dump'

width=200  
height=150  

f=open(file_path,'rb')  
data=f.read()  
p=Image.frombytes('RGB',(width,height),data)  
p=p.transpose(Image.FLIP_TOP_BOTTOM)  
p.show()  

事實上之前的長度600實我自己推得,題目中其實利用的150*200的圖像,只不過再驗證的時候用到了每一個像素點的三元組,所以驗證的長度是150*200*3==90000.我們最開始的寫法就是相當於把長拉長了,因爲是00或者ff所以結果沒有影響。

Position

這個題目,咋說呢,乍一看真的很嚇人,其實很簡單,只要看懂了就行,首先我們看一下很明顯得地方

這裏寫圖片描述

就是我們界面得地方,然後這個是MFC程序,代碼中動態檢查兩個文本框是否有輸入。通過文檔我們知道了一部分信息

1.serial的內容是76876-77776
2.密碼的最後一位是p

然後進入關鍵函數查看。這個長的令人髮指…但是我們只要仔細看結構和邏輯基本上都是很簡單的。就算靜態看不懂,我們只需要動態調試一下也就知道這是什麼情況了(這個處理確實比較簡單,中間很多就是簡單的加和,然後將int型轉換字符型,然後匹配),然後簡單總結一下就是

程序得流程
1.首先讀入兩個字符串 Name和Serial
2.驗證Name得長度是不是4
3.驗證Name組成得字符是不是都是a-z
4.驗證Name中是否存在相同得字符
5.驗證Serial得長度是不是11,且第6位是不是'-'
6.一大長串得驗證,具體看代碼吧

然後關於那一坨東西,我們只需要看代碼就一下子明白了

#_*_coding:utf-8_*_
import hashlib
serial = '76876-77776'
s = 'abcdefghijklmnopqrstuvwxyz'
first = []
second = []
for s1 in s:
    for s2 in s:
        value1_1 =  (ord(s1)&1)+5
        value1_2 =  ((ord(s1)>>4)&1)+5
        value1_3 =  ((ord(s1)>>1)&1)+5
        value1_4 =  ((ord(s1)>>2)&1)+5
        value1_5 =  ((ord(s1)>>3)&1)+5
        value2_1 =  (ord(s2)&1)+1
        value2_2 =  ((ord(s2)>>4)&1)+1
        value2_3 =  ((ord(s2)>>1)&1)+1
        value2_4 =  ((ord(s2)>>2)&1)+1
        value2_5 =  ((ord(s2)>>3)&1)+1  
        check1 = value1_1+value2_4
        if check1 != int(serial[0]):
            continue
        check2 = value1_5+value2_5
        if check2 != int(serial[1]):
            continue
        check3 = value1_3+value2_2
        if check3 != int(serial[2]):
            continue        
        check4 = value1_4+value2_1
        if check4 != int(serial[3]):
            continue        
        check5 = value1_2+value2_3
        if check5 != int(serial[4]):
            continue
        first.append(s1+s2)
        #print s1,s2
for s3 in s:
    for s4 in s:
        value1_1 =  (ord(s3)&1)+5
        value1_2 =  ((ord(s3)>>4)&1)+5
        value1_3 =  ((ord(s3)>>1)&1)+5
        value1_4 =  ((ord(s3)>>2)&1)+5
        value1_5 =  ((ord(s3)>>3)&1)+5
        value2_1 =  (ord(s4)&1)+1
        value2_2 =  ((ord(s4)>>4)&1)+1
        value2_3 =  ((ord(s4)>>1)&1)+1
        value2_4 =  ((ord(s4)>>2)&1)+1
        value2_5 =  ((ord(s4)>>3)&1)+1  
        check1 = value1_1+value2_4
        if check1 != int(serial[6]):
            continue
        check2 = value1_5+value2_5
        if check2 != int(serial[7]):
            continue
        check3 = value1_3+value2_2
        if check3 != int(serial[8]):
            continue        
        check4 = value1_4+value2_1
        if check4 != int(serial[9]):
            continue        
        check5 = value1_2+value2_3
        if check5 != int(serial[10]):
            continue
        second.append(s3+s4)
        #print s3,s4
print first
print second
for p1 in first:
    for p2 in second:
        value = p1+p2
        bit = []
        flag = 1 
        for check in value:         #一定要注意需要驗證4位數之間不能出現重複得字母
            if check in bit:
                flag = 0
                break
            else:
                bit.append(check)
        if flag ==1:
            if value[3]=='p':       #題目給的限定條件,最後一位是p
                print value

然後得到了3歌結果,看到了有意義的一個bump

Direct3D FPS

這個題目一開始就嚇我一跳,這是CS?然後解壓可以看到一個data文件夾,一個可執行文件,一個dll(警覺),然後發現卡的不行,看到FPS貌似是幀數,但是也不知道要幹啥,所以就打開IDA隨便看一下,看一下字符串

這裏寫圖片描述

感覺可能題目的意思就是想辦法讓我們結束戰鬥吧,但是…這真的是簡單題目???!!!
這裏寫圖片描述

然後後面有一個彈窗,感覺應該沒什麼問題…所以我們進行一下嘗試把(最後證明以後碰到這種東西不要虛,直接上去試試…)首先我們需要解決一個問題,就是我們不可能真的做到game over的條件了(沒分析也不知他是什麼條件要求,但是我們可以),所以就胡亂改一下把…修改跳轉指令
這裏寫圖片描述

然後就過去了,但是我們看到這裏是亂碼,這就確信了這個就是答案,你不可能通關了給你個亂碼把!
這裏寫圖片描述

所以需要知道有沒有別的地方調用修改了這個地方,要不說IDA是個好東西…可以直接看到啊(所以前面不是很有必要了…因爲靜態居然可以看到…)然後我們看一下靜態的內容長度應該在56之內把
這裏寫圖片描述

然後看到另一個關鍵的函數段
這裏寫圖片描述

看到這個關鍵的內容,這個result如何要處理的話應該時從0遍歷的。而且這個抑或的byte_409184是動態獲取的,而且感覺這個所謂的*4什麼的只是一個索引的作用。我們姑且就讓他從0-52跑一遍,這個函數觸發的時候時射擊的時候,但是不知道它到底是做什麼的…
而且貌似result也不是從0-52,一直是-1啊…然後乾脆走一走地圖…發現了這個小東西
這裏寫圖片描述

幹他一槍,發現返回的result變了額!
這裏寫圖片描述

然後經過測試發現,每一個小人應該是有一個不同的ID一樣的東西,result返回的就是這個東西!這下子明白了,也就是說勝利的條件是打過所有的小人唄!然後每個小人會處理一位…好吧,明白了
不過我們不能一個個都打把!而且這個每次修改result的值?這太麻煩了…然後忍不住查了一下別人怎麼做的…IDApython!!!

print bytearray( [(Byte( 0x1b7028+i ) ^ Byte(0x1b9184+(i*0x210))) for i in range(56)] )

真是學習了一波老哥^_^(記得運行的時候再執行腳本)

這裏寫圖片描述

其實我們如果可以找到byte_409184索引的位置也是沒問題的…,每一個對應的位置是byte_409184+0x210*n,最後觀察發現是有規律的,就是byte_409184+0x210*n==4*n
然後也可以直接寫解密腳本

import hashlib
flag = ''
cipher = [67, 107, 102, 107, 98, 117, 108, 105, 76, 69, 92, 69, 95, 90, 70, 28, 7, 37, 37, 41, 112, 23, 52, 57, 1, 22, 73, 76, 32, 21, 11, 15, 247, 235, 250, 232, 176, 253, 235, 188, 244, 204, 218, 159, 245, 240, 232, 206, 240, 169]
for i in range(len(cipher)):
    flag += chr(cipher[i]^(i*4))
print flag

回頭想想還是挺簡單的,但是千萬別被題目嚇住額…

Ransomware

首先拿到了程序用 IDA反編譯一下發現貌似唄加殼了,然後查一下殼吧,發現匹配不出來,但是貌似有什麼UPX這個字段,很敏感

這裏寫圖片描述

然後我們利用ESP定律進行脫殼吧,找到了程序得真正入口點是
這裏寫圖片描述

然後利用OLLYDB得dump工具進行脫殼,然後進一步看一看程序到底是啥!結果解壓出來了一個10M多得東西???!!!woc,不會吧…而且我們繼續觀察一下貌似關鍵得代碼部分會有很多很多得混淆…這就尷尬了…從0044A775往上有很多廢物代碼
這裏寫圖片描述

真實垃圾限制了我的想象力,然後需要嘗試IDApython解決這個事情!然後我明明寫的代碼沒什麼問題,但是死活就是得不到結果…

start = 0x401006
end = 0x4135CE
for i in xrange(start,end):
    PatchByte(i,0x90)

start = 0x4135E9
end = 0x44A775
for i in xrange(start,end):
    PatchByte(i,0x90)

結果調出來Graph view然後按下F5就行了,不明白爲什麼…

從從網上還看到有人直接匹配文件中得特殊字符

這裏寫圖片描述

data = open('111.exe','rb').read()
data = data.replace('\x60\x61\x90\x50\x58\x53\x5b','\x90\x90\x90\x90\x90\x90\x90')
open('777.exe','wb').write(data)

比較取巧但是也是解決得方法!然後我們就可以問題具體得加密流程了

這裏寫圖片描述

真正得算法非常簡單,但是我們需要注意得是沒有辦法根據反編譯找出密鑰,我胡亂輸入一個數字後,這時候我們看一下file得規律
這裏寫圖片描述

這個明顯是有規律得,但是我們也不是很確定,之後嘗試果真有不小問題…然後我們注意到TXT中得
這裏寫圖片描述

exe是用一些固定得明文串的,這算是小技巧吧,利用一下
這裏寫圖片描述

key1 = [0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,0x6d,0x6f,0x64,0x65]
key2 = [0xc7,0xf2,0xe2,0xff,0xaf,0xe3,0xec,0xe9,0xfb,0xe5,0xfb,0xe1,0xac,0xf0,0xfb,0xe5,0xe2,0xe0,0xe7,0xbe,0xe4,0xf9,0xb7,0xe8,0xf9,0xe2,0xb3,0xf3,0xe5,0xac,0xcb,0xdc,0xcd,0xa6,0xf1,0xf8,0xfe,0xe9]
flag = ''
for i in range(len(key2)):
    flag += chr(((~key2[i])%256)^key1[i])
print flag

得到密鑰letsplaychess,然後去解密程序即可,得到了程序運行不起來,發現還是UPX加殼,脫殼之後繼續看看源碼算了…找到了結果

這裏寫圖片描述

然後看到了人家得wp發現一個用IDApython處理將冗餘得sub401000函數去掉的方法!Σ(っ °Д °;)っ,學習一波得…

#_*_ coding:utf-8 _*_
import idaapi
ea = 0x0044A775     #_main函數實際作用的位置
StartAddress = LocByName('_main')  #獲得_main函數的起始地址
func = idaapi.get_func(StartAddress)    #獲得目標函數,輸入地址是函數的起始地址
EndAddress = func.endEA     #獲得函數的結束地址
while ea <= EndAddress:     #遍歷函數
    ea = FindCode(ea,SEARCH_DOWN | SEARCH_NEXT) #找到代碼位置
    if GetMnem(ea) == 'call' and GetOpnd(ea,0) == 'sub_401000': #匹配字符串,前面是助記符,後面是操作數
        for i in range(5):      #長度是5是觀察出來的call sub_401000
            PatchByte(ea+i,0x90)    #打patch嘍

果真IDApython還是很厲害的!效果如下

這裏寫圖片描述

學習到了,膜

Easy_ELF

做個簡單的先換換腦子

這裏寫圖片描述

簡單明瞭直接了當…來到關鍵函數簡單一分析就得出結論了…

L1NUX

Twist1

好好做提了…這個題目首先運行沒什麼問題,然後IDA看也沒什麼,不看具體內容先,然後OLLYGDB跑的時候會崩潰?瞬間警覺,然後返回IDA看一下代碼發現其實代碼不全,估計是一個花指令的東西。我們一步一步來(我沒分析過,就是自己試試好了)首先是

這裏寫圖片描述

在這個地方修改了原來的代碼,之後變成了這個
這裏寫圖片描述

可以看一下這個是啥東西啊,是防止靜態的一種簡單的花指令
這裏寫圖片描述

可以看到,這個時候al=0x9d
這裏寫圖片描述

看看變成了什麼
這裏寫圖片描述

然後和前面有一個pushf,而且這裏我們還要動態修改一個地方,最後成了
這裏寫圖片描述

可以看到最後跳回了0x40700D,上面的0x407030函數完全就是一個可執行花指令函數。
這裏寫圖片描述

再之後其實沒什麼,就是將0x40702F改成了0x407008,然後又去call了一下0x407030,就是又是一個花指令函數的過程,之後會跳到
這裏寫圖片描述

後面沒法繼續完全分析了,發現越來越多…我覺得應該是某些殼…要不然也太多了…不管怎樣還是繼續調試,這個花指令就是防止靜態的調試,再動態過程中不斷修改代碼達到跳轉到主函數的目的,最後找到一個長跳轉很像OEP

這裏寫圖片描述

這裏寫圖片描述

可以看到了push什麼什麼,很像主函數的東西嘍,然後實驗成功脫殼.然後看了一下代碼就很簡單了,貌似就一個判斷函數而已,前面都是字符串的輸入輸出
這裏寫圖片描述

然後繼續想動態調試調試出最關鍵的地方,但是還是沒有解決一Ollygdb調試就崩潰…what?但是這裏崩潰的位置是這個
這裏寫圖片描述

調試的時候發現除以0了,所以先nop掉再說,後面所謂的比較函數sub_401240只是一個假象,首先是將輸入字符串的數值放到了byte_40B970之中,然後來了個大跳轉???
這裏寫圖片描述

但是那個地方什麼都沒額…我覺得這個操作應該是故意改錯的吧?也不對啊…那源程序怎麼就跑的起來…百思不得其解…參考一下大牛說那裏有東西???!!!what???不知道說什麼好了…不知道什麼原因dump下來就沒東西…只能每次都脫殼?結果看一下還真有東西…(爲啥啊!)
這裏寫圖片描述

調用了什麼ZwQueryInformationProcess
調試的過程中發現,如果這個位置不匹配就會陷入死循環
這裏寫圖片描述

總共拷貝了16個字節到這個地方…但是我發現還是死循環…在驗證00407275時候死活過不去???這又是啥…複製的地址是7757E990,應該是系統函數,後面找到了是ntdll.dll,系統函數?這個還能錯得話就是…系統不對???想到了Readme…
這裏寫圖片描述

老老實實放回32位XP下跑吧…
這裏寫圖片描述

造孽啊…果然放到了XP下就沒任何問題了…而且能夠驗證之前dump下來得脫殼文件確實不行…會運行崩潰…
然後我們繼續分析把,剛剛拷貝得16個字節得內容就是我們後面要調用得函數,再往後調用得過程中OLLydbg停止了,是反調試技術了。查找了資料是queryInformationProcess()函數相關得反調試函數
這裏寫圖片描述

然後通過查找資料調用得函數應該具體是ProcessDebugPort(0x7)和ProcessDebugObject-Handle(0x1E)還有ProcessDebugFlags(0x1F),具體是什麼簡單介紹一下

ProcessDebugPort(0x7)
進程處於調試狀態,系統會爲它分配一個調試端口,ProcessInformationClass參數的值爲ProcessDebugPort(0x7).若程序處於非調試狀態,則變量dwDebugPort的值設置爲0,若進程處於調試狀態,則值設置爲0xFFFFFFF.

ProcessDebugObjectHandle(0x1E)
調試進程時會生成調試對象,函數的第二個參數值爲ProcessDebugObjectHandle,調用參數後就能獲取調試對象句柄,進程處於調試狀態時,調試對象句柄的值就存在,若進程處於非調試狀態,則調試對象句柄值爲NULL.
ProcessDebugFlags(0x1F)
檢測debug flag調試標誌的值也可以判斷是否處於被調試狀態,函數 的第二個參數設置爲processdebugflag(0x1)時,調用函數後通過第三個參數即可獲的調試標誌的值,若爲0,則進程處於被調試狀態,若爲1,則進程處於非調試狀態。

然後直接全部nop掉好了
然後繼續,取出了第一位和第七位放到了新的內存中(再次提醒一下輸入的地址事0x40b970)

這裏寫圖片描述

後面調着調着又又又結束進程了!!!!這回又是啥…然後找到出問題的地方,發現使用了GetThreadContext函數,作用是獲取硬斷點的內容…之前我下了硬斷點,所以這裏就gg了…然後解決的方法是再每次jnz跳轉的時候修改掉寄存器的值或者test eax之前將eax置零。
然後我們可以看到一個東西!
這裏寫圖片描述

這個就是我們之前輸入字符串第七位與0x36抑或的值,比較是不是0x36,那麼就是說第七位已經是末尾之後了,字符串很可能是6位(7位以下嘛)

然後第一位的匹配,我實在懶得再去截圖了,是這樣的

1.將第一位ror al 6
2.將移位後的值和0x49比較

得知第一位是R
然後繼續觀察可以得到

第二位 ^0x20==0x69  I

第三位 ^0x77==0x35  B

第四位 ^0x21==0x64  E

第五位 ^0x46==0x8   N

第六位 rol dl 4 之後與0x14比較

最後得到了整個解題的答案…

RIBENA

這裏寫圖片描述

woc…這題實在是挺難的…搞了兩三天才弄完…真是…總結一下這個題目的考點…

1.首先本來是脫殼,但是不知道爲什麼脫殼後dump下來的數據是殘缺的,現在懷疑是程序本身的東西,可能加了個線程什麼的實現的,實際上我們知道OEP就行了
2.反調試技術,裏面有一些坑點,比如調用的queryInformationProcess()檢測進程是否爲調試狀態,再比如GetThreadContext檢測程序是否有硬斷點...
3.然後中間有內存的來回切換,需要十足的細心
4.考驗用ollygdb的運用能力

總之對我來說確實很難了,太菜了…/(ㄒoㄒ)/~~

AutoHotkey1

查殼看不出來,但是還是需要手動脫殼把應該(至少需要知道OEP在哪裏)
然後我們找到OEP應該是

這裏寫圖片描述

然後我找到了輸入的地方,並在後面下了斷點,然後再輸入之後歪打正着找到一個….
這裏寫圖片描述

然後輸入54593f6b9413fc4ff2b4dec2da337806就會顯示
這裏寫圖片描述

什麼鬼,但是題目肯定不是這麼做的,提交結果也不對,我認爲只是誤打誤撞找到了部分答案。其實我一開始一直沒弄懂Readme幾個意思,後來明白其實需要提交AuthKey吧,然後我們需要找到DecryptKey和EXE’s Key了。

使用upx -d解密文件,發現是這樣的

這裏寫圖片描述

然後再GDB裏面找到字符串,然後跟到了這裏
這裏寫圖片描述

然後就看到eax被賦值時3了,然後用IDA大概看一下發現這個應該時判定文件是否被修改過而已。然後這裏我們將je條件改變使之能夠跳過這一步。這附近的邏輯大概是這樣的
這裏寫圖片描述

所以這個地方的函數判斷也非常重要,必須通過,否則程序也無法運行
這裏寫圖片描述

然後點進去看,發現時這樣的
這裏寫圖片描述

然後觀察得到sub_450DCA之中用到了多次sub_450ABA,而且另一個分支之中sub_450ABA也用到了很多次,於是這應該是一個類似驗證的函數,而且我們觀察到我們upx -d之後函數會在這裏附近結束,估計這個時驗證文件是否被修改的函數。那麼如何驗證,估計就有一個MD5比較吧!試試就知道了。
使用源文件(沒有改過的),然後在sub_450DCA下斷點,然後一步步看。
這裏寫圖片描述

在這一步得到了寄存器的值220226394582d7117410e3c021748c2a

再結合前面的…MD5解密得到

isolated pawn

woc。。。這還是投機取巧了,沒讓你分析具體的算法什麼的,這個題目就是看你逆向的一些套路了,能不能大概猜到他的作用,需要多嘗試,多猜想驗證…(本題後面都是參考大佬了,太菜了…套路不夠深…)





















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章