攻防世界RE練習

攻防世界

一開始學習下re,產生了興趣html

 game

這個題目在某個CTF平臺作過了0-0,再作一遍。(跟着WP 0.0)python

首先用ExeinfoPe或者Peid查殼linux

 

也可使用file命令查看相關信息c++

 32位程序,使用ida打開,F5反編譯git

程序邏輯:github

 

 

shift+F12 查看字符串ubuntu

 

進入後windows

右鍵list cross reference to ,而後F5centos

 

 

 

 

這就是求flag的過程,而且輸出,我能夠寫一個py腳本讀出來數組

在這裏的*(&v2+i)至關於v[2+i],數組形式的格式,其實就是遞加1==>v2,v3,v4

注:由於初入RE不知道怎麼提取,索性複製粘貼,而後運行exec動態變量合併變量值組成數組

exec()函數
v59 = 18 v60 = 64 v61 = 98 v62 = 5 v63 = 2 v64 = 4 v65 = 6 v66 = 3 v67 = 6 v68 = 48 v69 = 49 v70 = 65 v71 = 32 v72 = 12 v73 = 48 v74 = 65 v75 = 31 v76 = 78 v77 = 62 v78 = 32 v79 = 49 v80 = 32 v81 = 1 v82 = 57 v83 = 96 v84 = 3 v85 = 21 v86 = 9 v87 = 4 v88 = 62 v89 = 3 v90 = 5 v91 = 4 v92 = 1 v93 = 2 v94 = 3 v95 = 44 v96 = 65 v97 = 78 v98 = 32 v99 = 16 v100 = 97 v101 = 54 v102 = 16 v103 = 44 v104 = 52 v105 = 32 v106 = 64 v107 = 89 v108 = 45 v109 = 32 v110 = 65 v111 = 15 v112 = 34 v113 = 18 v114 = 16 v115 = 0 v2 = 123 v3 = 32 v4 = 18 v5 = 98 v6 = 119 v7 = 108 v8 = 65 v9 = 41 v10 = 124 v11 = 80 v12 = 125 v13 = 38 v14 = 124 v15 = 111 v16 = 74 v17 = 49 v18 = 83 v19 = 108 v20 = 94 v21 = 108 v22 = 84 v23 = 6 v24 = 96 v25 = 83 v26 = 44 v27 = 121 v28 = 104 v29 = 110 v30 = 32 v31 = 95 v32 = 117 v33 = 101 v34 = 99 v35 = 123 v36 = 127 v37 = 119 v38 = 96 v39 = 48 v40 = 107 v41 = 71 v42 = 92 v43 = 29 v44 = 81 v45 = 107 v46 = 90 v47 = 85 v48 = 64 v49 = 12 v50 = 43 v51 = 76 v52 = 86 v53 = 13 v54 = 114 v55 = 1 v56 = 117 v57 = 126 v58 = 0 a=[] for i in range(59,116): exec('a.append(v{})'.format(i)) print(a) b=[] for i in range(2,59): exec('b.append(v{})'.format(i)) print(b) i=0 c='' while (i<56): a[i]^=b[i] a[i]^=19 c=c+chr(a[i]) i=i+1 print (c)
輸出:
[18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0]
[123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121, 104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13, 114, 1, 117, 126, 0]
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}
locals()函數
v59 = 18 v60 = 64 v61 = 98 v62 = 5 v63 = 2 v64 = 4 v65 = 6 v66 = 3 v67 = 6 v68 = 48 v69 = 49 v70 = 65 v71 = 32 v72 = 12 v73 = 48 v74 = 65 v75 = 31 v76 = 78 v77 = 62 v78 = 32 v79 = 49 v80 = 32 v81 = 1 v82 = 57 v83 = 96 v84 = 3 v85 = 21 v86 = 9 v87 = 4 v88 = 62 v89 = 3 v90 = 5 v91 = 4 v92 = 1 v93 = 2 v94 = 3 v95 = 44 v96 = 65 v97 = 78 v98 = 32 v99 = 16 v100 = 97 v101 = 54 v102 = 16 v103 = 44 v104 = 52 v105 = 32 v106 = 64 v107 = 89 v108 = 45 v109 = 32 v110 = 65 v111 = 15 v112 = 34 v113 = 18 v114 = 16 v115 = 0 v2 = 123 v3 = 32 v4 = 18 v5 = 98 v6 = 119 v7 = 108 v8 = 65 v9 = 41 v10 = 124 v11 = 80 v12 = 125 v13 = 38 v14 = 124 v15 = 111 v16 = 74 v17 = 49 v18 = 83 v19 = 108 v20 = 94 v21 = 108 v22 = 84 v23 = 6 v24 = 96 v25 = 83 v26 = 44 v27 = 121 v28 = 104 v29 = 110 v30 = 32 v31 = 95 v32 = 117 v33 = 101 v34 = 99 v35 = 123 v36 = 127 v37 = 119 v38 = 96 v39 = 48 v40 = 107 v41 = 71 v42 = 92 v43 = 29 v44 = 81 v45 = 107 v46 = 90 v47 = 85 v48 = 64 v49 = 12 v50 = 43 v51 = 76 v52 = 86 v53 = 13 v54 = 114 v55 = 1 v56 = 117 v57 = 126 v58 = 0 a=[] v=locals() for i in range(59,116): a.append(v['v'+str(i)]) print(a) b=[] for i in range(2,59): b.append(v['v'+str(i)]) print(b) i=0 c='' while (i<56): a[i]^=b[i] a[i]^=19 c=c+chr(a[i]) i=i+1 print (c)
輸出:

[18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0]
[123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121, 104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13, 114, 1, 117, 126, 0]
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

 

Hello CTF

查殼,32位,F5反編譯

 

 

 

代碼的邏輯就是賦予V13爲437261636b4d654a757374466f7246756e

輸入的長度若是大於17直接break,do while循環17次,中間若是有一個爲0的話,就會直接break出循環。沒有出現0的話,賦值給v10 直接比較V10和V13是否相等,strcmp相等返回0,提示success

 

這裏有個很明顯的地方,就是長度17,而437261636b4d654a757374466f7246756e的長度爲34,應該是兩個兩個爲一組,16進制的表示。

解密腳本:

import re
MW='437261636b4d654a757374466f7246756e' secret=re.findall(r'.{2}',MW) flag='' for i in secret: flag+=chr(int(i,16)) print('flag:'+flag)
輸出:
flag:CrackMeJustForFun

open-source

一個C文件,放出centos7中, gcc編譯下, gcc code.c

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) { if (argc != 4) { printf("what?\n"); exit(1); } unsigned int first = atoi(argv[1]); if (first != 0xcafe) { printf("you are wrong, sorry.\n"); exit(2); } unsigned int second = atoi(argv[2]); if (second % 5 == 3 || second % 17 != 8) { printf("ha, you won't get it!\n"); exit(3); } if (strcmp("h4cky0u", argv[3])) { printf("so close, dude!\n"); exit(4); } printf("Brr wrrr grr\n"); unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207; printf("Get your key: "); printf("%x\n", hash); return 0; }

沒學過C,可是看到argv[],與py中的sys.argv應該是同樣的。就是獲取命令輸入的參數

argc是argumentcount的縮寫,表示傳入main函數的參數個數

argv 是argument vector的縮寫,表示傳入main函數的參數序列或指針

argv數組下標從0開始,第一個存放的是可執行程序的文件名字

argc[0]表示程序編譯後產生的exe文件的路徑,數組的長度爲argc

第一個條件:

if (argc != 4) {
printf("what?\n");
exit(1);
}

輸入的參數要爲3個   argc第一個參數爲路徑

第二個條件:

unsigned int first = atoi(argv[1]);
    if (first != 0xcafe) { printf("you are wrong, sorry.\n"); exit(2); }

第一個參數爲0xcafe轉爲十進制數51966

第三個條件:

    unsigned int second = atoi(argv[2]);
    if (second % 5 == 3 || second % 17 != 8) { printf("ha, you won't get it!\n"); exit(3); }

第二個參數須要不知足任意一個條件=>整除5餘3,整除17餘數不能爲8。   所以argv[2] 由於25

第四個條件:

if (strcmp("h4cky0u", argv[3])) {
        printf("so close, dude!\n"); exit(4); }

若是第三個參數與h4cky0u相等則返回0繞過if。所以第三個參數爲h4cky0u

並不是逆向題目,而是C語言的簡單源碼審計問題

 

simple-unpack

看描述:菜雞拿到了一個被加殼的二進制文件

我估計是要脫殼。

在這裏停一下,去補一下RE基礎知識

回來繼續看題,二進制文件,不知道該怎麼處理。看WP

我用了V2.04版本的Die和exeinfo PE查殼發現能夠直接查看到是upx,可是peid不行。

 

 

 

 

 注:windows下的文件是PE文件,Linux/Unix下的文件是ELF文件

PE文件的全稱是Portable Executable,意爲可移植的可執行的文件,常見的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微軟Windows操做系統上的程序文件(多是間接被執行,如DLL)

經過在愛盤下載了upx(去官網,github下載太慢了,氣死)

用upx -d 命令解壓脫殼

 

 

 

 

 

 利用linux中的strings工具也能找到(cmder沒有)

 

 

logmein

明天開始上課了,明兒作把。9.2 0:19

 

 die太強大了。64位的elf,而且由ubuntu gcc編譯

 

 

 繞過三個條件記能返回成功

 

 沒看wp,本身寫了個腳本跑出來8#DO_SVZI*-9*4*2發現不對。再去看下WP把

原理這是是有個大小端存儲的問題,而且LL是指長整型

能夠按R鍵轉化數據爲字符(10進制轉16進制,16進制轉字符),而且看到了倒序的賦值=》能夠推斷爲小端存儲

小端存儲:低字節存儲在低地址,高字節存儲在高地址

大端存儲:高字節存儲在低地址,低字節存儲在高地址

 

 所以不能光看僞代碼,也要結合着彙編看代碼段。

因不會C代碼0-0,因此只能用py解,附上別人寫的C代碼寫的腳本

py腳本以下:

v8=':"AL_RT^L*.?+6/46'
v7='ebmarah'
v7=v7[::-1]
v6=7
s=''
for i in range(0,17):
s+=chr((ord(v7[i%7]))^ord(v8[i]))
print(s)

C腳本以下:

#include <stdio.h>
#include <stdlib.h> #include <string.h> #define BYTE unsigned char int main(int argc, char* argv[]) { unsigned int i; char v8[18] = ":\"AL_RT^L*.?+6/46"; __int64 v7 = 28537194573619560; int v6 = 7; char s[18] = ""; for (i = 0; i < strlen(v8); ++i) { s[i] = (char)(*((BYTE*)&v7 + i % v6)^v8[i]); } printf("%s\n", s); system("PAUSE"); return 0; }

 

insanity

 先查看,看類型

 

 

 

 

 

 

 

 還真是跟題目描述同樣,輕鬆一下。9447{This_is_a_flag}

 

no-strings-attached

查殼

 

 

 進入prompt_autthentication

 

有一個decrypt函數

 

 

 

 

看WP須要動態調試,蒙了。多是函數運行,數據存在於寄存器中把。看WP寫把

gdb經常使用命令

gdb -q xxxx 將文件加載到GDB中

b decrypt 設置斷點,decrypt函數

r 運行

s: 執行一行源程序代碼,若是此行代碼中有函數調用,則進入該函數;
n: 執行一行源程序代碼,此行代碼中的函數調用也一併執行。

s 至關於其它調試器中的「Step Into (單步跟蹤進入)」;
n 至關於其它調試器中的「Step Over (單步跟蹤)」。

x 就是用來看內存中的值

info reg 查看寄存器

info break查看斷點列表

$eax表明的eax寄存器中的值

到00表示終止了

十六進制表示爲:393434377b796f755f6172655f616e5f696e7465726e6174696f6e616c5f6d7973746572797d

 

 

 

 py2中還有decode('hex'),直接十六進制轉化爲字符串,py3中沒有了

RE頗有意思,慢慢來,明早起來看WEB,看以前的難題WP了。

 

python-trade

下下來是一個pyc,直接網上在線的反編譯下

import base64

def encode(message): s = '' for i in message: x = ord(i) ^ 32 x = x + 16 s += chr(x) return base64.b64encode(s) correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' flag = '' print 'Input flag:' flag = raw_input() if encode(flag) == correct: print 'correct' else: print 'wrong'

代碼十分簡單,寫一個解密腳本

 

 

 

getit

查殼

 

 

 

 貌似是通過一些條件後,寫入文件而後又刪除的操做

把t寫入了flag.txt中,那t應該就是flag。上面還有關於s賦值給t的操做。

0前面的這一塊是定義t的,看數據塊最後的10E0,10E1,下面是110C

 

0前面的這一塊是定義s的

 

這樣都有了s和t了,呢麼直接寫腳原本找到寫入的t

直接上解密腳本

t='SharifCTF{????????????????????????????????}'
t=list(t) s='c61b68366edeb7bdce3c6820314b7498' v5=0 while(v5<len(s)): if(v5&1): v3=1 else: v3=-1 t[v5+10]=chr(ord(s[v5])+v3) v5+=1 yunying='' for i in t: yunying+=i if __name__ == '__main__': print(yunying)

 

 

 

 csaw2013reversing2

註釋:據說運行就能拿到Flag,不過菜雞運行的結果不知道爲何是亂碼

查殼 vc++,32位

 

 

 

 無論點哪一個按鈕都直接退掉了。估計是須要調試跳到正確的函數上(可能又是動調)

ida main函數界面:

 

 這裏能夠看到比較清晰的程序運行路徑

 

 

int3 =>是一個斷點,int3斷點

MessageBox 函數用於建立、顯示並操做一個消息對話框。該對話框包含由調用程序定義的信息和標題,以及預先定義的圖標和按鈕

看到IsDebuggerPresent()函數,查文章得到=> https://bbs.pediy.com/thread-226522.htm=>學到一手,大部分的函數返回值都在eax中。難怪以前的decrypt函數須要gdb動態調試到函數查看eax

IsDebuggerPresent()函數是判斷程序是否在調試中,由於一些程序爲了避免被Craker,加入這個函數。

參考(http://www.javashuo.com/article/p-bymjqbzg-ds.html)od調試(只會一點點)

這裏的邏輯是若是是在調試中的話就進入判斷運行,若是不在調試中的話直接彈出亂碼flag

sub_401000是解密函數,[ebp+lpMem]是亂碼存放的地方

sub_401000函數分析出來是將亂碼的flag4個字節爲一組與0xAABBCCDD異或獲得可識別的flag

花了一個小時看OD的WP,沒看懂,仍是經過IDA來分析把。

sub_401000是解密函數,進入查看

409B10數據以下

 

409B38處,由於是小端存儲,所以須要倒一下

 

 附上別人的WP腳本(OD不會到心態炸裂,無意靜態分析)

cipher = [0xbb, 0xcc, 0xa0, 0xbc, 0xdc, 0xd1, 0xbe, 0xb8, 0xcd, 0xcf, 0xbe, 0xae, 0xd2, 0xc4, 0xab, 0x82, 0xd2, 0xd9, 0x93, 0xb3, 0xd4, 0xde, 0x93, 0xa9, 0xd3, 0xcb, 0xb8, 0x82, 0xd3, 0xcb, 0xbe, 0xb9, 0x9a, 0xd7, 0xcc, 0xdd]
key = [0xbb,0xaa,0xcc,0xdd] flag = '' for i in range(len(cipher)): flag += chr(cipher[i]^key[i%4]) print flag ———————————————— 版權聲明:本文爲CSDN博主「Prowes5」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/Prowes5/article/details/100409391

RE到此爲止,衝WEB

9.29重作,用OD動調找到了flag,開森。最近學了一些彙編知識,正好派上了用場。開心

 

 先ida靜態分析

 

 

 

 能夠看出有個IsDebuggerPresent,意思是若是在調試中返回非零值,若是不是則直接返回0

咱們應該是須要進入這裏,sub_401000應該是一個解密函數,而且上面有int 3 斷點

 

 利用OD載入,查找ASCII,找到flag,在00BB1088處斷點

 

即跳過ISDebuggerpresent函數,進入解密區

 

 下斷點單步F8運行

 

發現直接跳到了00BB10B9這裏,中間跳了呢麼多,咱們嘗試修改未跳轉的jnz,讓他跳轉到下面被跳過的區域。查看下會發生什麼

修改je而且nop了int3後,又有一個想跳轉出去,不執行裏面的東西,確定有蹊蹺。

 

 

 

 很想在ida中進行的以下步驟

 

 nop掉繼續嘗試,text裏什麼都沒有

 

又想要跳出去,不行,接着看

 

 發現nop後,也沒法繼續單步運行。那就嘗試跳轉到下面的語句中。有兩個MessageBoxA,那確定有一個是假的

 

 繼續單步F8,F7是步入,會進入call函數。不必

 

 

 

 其實與ida上的靜態分析是同樣的,咱們須要進入if判斷中,而且讓解密函數運行即彙編中的解密call指令運行,可是不能讓他直接退出,要讓將咱們解密後須要的值返回到一個能夠看到的變量上,將之跳轉到第二個Messagebox上,值就會傳到Text上。第一個Messagebox是設置的陷阱,不能nop而是要避開而且跳轉到正確的Messagebox上。

設置的斷點最好也要取核心位置,正要進入判斷的位置上,學到了不少。悟通了

 經過IDA和OD的對比也能發現解密函數其實就是那個被跳過的Call

 

 

maze

查殼,elf文件,64位,GCC編譯,amd64

 

 

 

 繞過第一個if,須要輸入的前五個字符與nctf{相等,而且輸入的字符須要24位,而且最後一位必須是}

若是大於N進入第一個if,判斷是不是大寫O或小寫0,進入不一樣的函數。若是小於N,是否等於.或者0在進入不一樣的函數

題目描述是一個迷宮,可能O,o,.,0表明着上下左右。而且最後要通過

 

 

 

 繞過這個if,使之相等後,才能Congratulations!

咱們來查看等於O,o執行的函數

O:

 

 o:

 

 .:

 

 0:

 

分析得V9應該是存儲座標的地方,而且每走一步,都會判斷,若是超出限制範圍,就會直接回到LABEL_22處,puts('wrong flag')

 

 最後會判斷是否等於35,不等的話,直接wrong,flag。相等的話,就是LABEL_20

 

 這裏能夠看出,當走完後,若是不是#的話,仍是wrong flag,所以能夠判斷#就是咱們須要走到的重點。

SHIDWORD是取下一個字節的意思,再結合上面的O,o,.,0,和迷宮的字符數量爲64。因此是8*8的地圖

所以V9應該是行數,V9+1是下一個字節的地址,表示的是列

所以把迷宮搞下來,變成8*8

 

 shift+e,搞下來用py腳本,變成8*8

# -*- coding: utf-8 -*-
a='  *******   *  **** * ****  * ***  *#  *** *** ***     *********'
for i in range(0,len(a)):
    if(i%8==0):
        print('')
    print(a[i],end='')

 

 

右下右右下下左下下下右右右右上上左左

o0oo00O000oooo..OO

flag就是nctf{o0oo00O000oooo..OO}

終於解完了RE的新手題目

dmd-50

suctf-2016題目

國慶10.1分還無聊到作RE題?我大概是蛋疼極了

查殼

 

 

 

 

 很是的多,邏輯上看起來不復雜,其中還有一個MD5的函數,就是看不懂這些C中的頭文件類啊定義什麼的。(學過半年的C++,只是應付考試QAQ)

運行以下

 

 

 注意下這裏,V41是由V40傳過來的,而後上面有個MD5函數

應該是md5後,若是是每一位對照下面的這個md5哈希值的話,若是相同的話,彈invaild key,所以只要把哈希值解一遍就好

 

 

 

 

 

 直接交flag就完事了。(對於那些C的東西,懵逼啊哎,也不會IDA中的idc和python腳本,每一個十進制ascii都是我按R按出來的)

Shuffle

題目描述是找到字符串在隨機化以前.

查殼

 

 

 

BUGKU

瞎玩玩

逆向入門

查殼

 

打開也打開不了.用ultraedit打開瞧瞧

 

 找個在線base64轉圖片的網站

 

 掃描拿到flag

love

查看

 

 32位C++,拖入ida

 

 

 

 

strncpy函數用於將指定長度的字符串複製到字符數組中,char *strncpy(char *dest, const char *src, int n),表示把src所指向的字符串中以src地址開始的前n個字節複製到dest所指的數組中,並返回被複制後的dest
strncmp函數爲字符串比較函數,字符串大小的比較是以ASCII 碼錶上的順序來決定,此順序亦爲字符的值。其函數聲明爲int strncmp ( const char * str1, const char * str2, size_t n );功能是把 str1 和 str2 進行比較,最多比較前 n 個字節,若str1與str2的前n個字符相同,則返回0;若s1大於s2,則返回大於0的值;若s1 小於s2,則返回小於0的值
  

這樣思路就比較清晰了。

首先傳入字符串,而後通過函數sub_4110BE後傳入v4

再將 v4的前28個字節傳入DEST數組中

 

 對DEST數組進行處理,而後比較str2和dest前v5個字符是否相等,相等則right flag!

查看一下函數

 

 

 

 

 

 v3是傳入字符串的長度,而後將a2除於3後,又乘上4,想到了什麼?base64加密

base64加密,一個字符佔6個字符,3個字符24個字節被加密成4個字符24個字節

呢麼直接上腳本,惟一處理的只有這兩處

 

 

 

 python3腳本

import base64
str1='e3nifIH9b_C@n@dH'
str2=''
for i in range(len(str1)):
    a=ord(str1[i])-i
    str2+=chr(a)
print(base64.b64decode(str2.encode('utf8')).decode())

 

 睡覺了

相關文章
相關標籤/搜索