生活随笔
收集整理的這篇文章主要介紹了
REVERSE-PRACTICE-BUUCTF-13
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
REVERSE-PRACTICE-BUUCTF-13
- firmware
- [ACTF新生賽2020]Oruga
- [Zer0pts2020]easy strcmp
- [GXYCTF2019]simple CPP
firmware
.bin(二進制)文件,由題目提示知是路由器固件逆向
參考:逆向路由器固件之解包 Part1
linux安裝好binwalk和firmware-mod-kit
binwalk會分析二進制文件中可能的固件頭或者文件系統(tǒng),然后輸出識別出的每個部分以及對應(yīng)的偏移量
binwalk該二進制文件,發(fā)現(xiàn)包含了squashfs文件系統(tǒng)(squashfs是linux下的一種只讀壓縮文件系統(tǒng)類型)
binwalk -e 該二進制文件,提取出各部分數(shù)據(jù)到各個文件,相當(dāng)于解壓固件,解壓出來的文件放在當(dāng)前目錄的/_firmware.bin.extracted文件夾下(注意此時的suqashfs-root文件夾是否為空)
使用firmware-mod-kit解包提取出來的squashfs文件
/*******************************************************
firmware-mod-kit的一些用法:
extract-firmware.sh 解包固件
build-firmware.sh 重新封包
check_for_upgrade.sh 檢查更新
unsquashfs_all.sh 解包提取出來的squashfs文件
*******************************************************/
解包squashfs文件出來的文件放在了當(dāng)前目錄的squashfs-root-1文件夾中
(實際上,在本人虛擬機binwalk -e 該二進制文件后,生成文件夾/_firmware.bin.extracted中的squashfs-root文件夾,已經(jīng)是解包squashfs文件出來的文件夾了,即squashfs-root文件夾和squashfs-root-1文件夾中包含的文件是相同的,如果squashfs-root文件夾下內(nèi)容為空,是由于sasquatch安裝有問題導(dǎo)致的,可以通過重新安裝sasquatch解決,參考:dir815_FW_102.bin路由器固件解壓碰到的坑)
在/_firmware.bin.extracted/squashfs-root/tmp目錄或/_firmware.bin.extracted/squashfs-root-1/tmp目錄下有一個backdoor文件
backdoor查殼發(fā)現(xiàn)有upx殼,脫殼后拖入ida分析
在字符串窗口找到網(wǎng)址
交叉引用網(wǎng)址,在initConnection函數(shù)中找到端口
[ACTF新生賽2020]Oruga
elf文件,無殼,ida分析
main函數(shù)邏輯清晰,獲取輸入,檢驗輸入是否為“actf{”開頭,驗證輸入內(nèi)容,以及最后一個字符是否為“}”
進入check函數(shù),分析可知是一個16x16的迷宮,和常規(guī)迷宮的按一次方向鍵則往該方向前進一格的機制不同,該迷宮的前進機制為,按一次方向鍵,則往該方向一直前進,直到撞到墻,具體分析知道,在map為零的位置時,可以持續(xù)前進,到達第一個非零的位置就停下來,然后減一個步長回到前一個零的位置,再讀input的內(nèi)容更新步長,更新步長實際上就是換方向
_BOOL8 __fastcall
check(__int64 input
)
{int index
; signed int input_index
; signed int step
; index
= 0;input_index
= 5;step
= 0;while ( map
[index
] != '!' ) {index
-= step
; if ( *(_BYTE
*)(input_index
+ input
) != 'W' || step
== -16 ){if ( *(_BYTE
*)(input_index
+ input
) != 'E' || step
== 1 ){if ( *(_BYTE
*)(input_index
+ input
) != 'M' || step
== 16 ){if ( *(_BYTE
*)(input_index
+ input
) != 'J' || step
== -1 )return 0LL;step
= -1; }else{step
= 16; }}else{step
= 1; }}else{step
= -16; }++input_index
; while ( !map
[index
] ) {if ( step
== -1 && !(index
& 0xF) ) return 0LL;if ( step
== 1 && index
% 16 == 15 )return 0LL;if ( step
== 16 && (unsigned int)(index
- 240) <= 0xF )return 0LL;if ( step
== -16 && (unsigned int)(index
+ 15) <= 0x1E )return 0LL;index
+= step
; }}return *(_BYTE
*)(input_index
+ input
) == '}';
}
把map提取出來,制成16x16的迷宮,按照前進機制走完迷宮即可,起始點為左上角的[0,0],終止點為“!”(0x21),W-上,M-下,J-左,E-右,路線即為flag
[Zer0pts2020]easy strcmp
elf文件,無殼,ida分析
main函數(shù),有一個比較字符串的if語句決定輸出的內(nèi)容,其他什么也沒有
來到start函數(shù),發(fā)現(xiàn)在調(diào)用main函數(shù)前,先調(diào)用了fini函數(shù)和init函數(shù)
fini函數(shù)直接返回了,分析init函數(shù),可以知道,在調(diào)用main函數(shù)前,程序?qū)?init_array段地址到.fini_array段地址之間的函數(shù)全部執(zhí)行一遍,命令行參數(shù)作為段之間函數(shù)的參數(shù)
這里可以看到,.init_array段和.fini_array段之間有3個函數(shù),依次分析知道,重要的是sub_795函數(shù)
sub_795->sub_6EA,分析sub_6EA函數(shù),計算輸入的長度,將輸入的內(nèi)容順序地與qword_201060數(shù)組的元素相減,然后去到main函數(shù)和那段字符串比較
寫腳本即可得到flag
[GXYCTF2019]simple CPP
exe程序,運行后提示輸入flag,輸入錯誤退出程序,無殼,ida分析
交叉引用字符串來到sub_140001290函數(shù)
__int64
sub_140001290()
{bool v0
; __int64 v1
; __int64 v2
; unsigned __int8
*v3
; unsigned __int8
*v4
; int v5
; __int64 v6
; _BYTE
*input_copy
; void **v8
; __int64 arr
[3]; __int64 arr
[2]; __int64 arr
[1]; __int64 arr
[0]; signed int v13
; unsigned __int8
*v14
; __int64 v15
; __int64
*v16
; __int64 v17
; __int64 v18
; _QWORD
*v19
; __int64 v20
; __int64 v21
; __int64 v22
; __int64 v23
; __int64 v24
; __int64 v25
; __int64 v26
; __int64 v27
; __int64 v28
; bool v29
; __int64 v30
; void *v31
; const char *v32
; __int64 v33
; _BYTE
*v34
; __int64 v36
; void *input
; unsigned __int64 input_len
; unsigned __int64 v39
; v0
= 0;input_len
= 0i64
;v39
= 15i64
;LOBYTE(input
) = 0;LODWORD(v1
) = printf(std
::cout
, "I'm a first timer of Logic algebra , how about you?");std
::basic_ostream
<char,std
::char_traits
<char>>::operator
<<(v1
, sub_140001B90
);printf(std
::cout
, "Let's start our game,Please input your flag:");sub_140001DE0(std
::cin
, &input
, v2
); std
::basic_ostream
<char,std
::char_traits
<char>>::operator
<<(std
::cout
, sub_140001B90
);if ( input_len
- 5 > 25 ) {LODWORD(v33
) = printf(std
::cout
, "Wrong input ,no GXY{} in input words");std
::basic_ostream
<char,std
::char_traits
<char>>::operator
<<(v33
, sub_140001B90
);goto LABEL_45
;}v3
= sub_1400024C8(32ui64
); v4
= v3
;if ( v3
) {*v3
= 0i64
;*(v3
+ 1) = 0i64
;*(v3
+ 2) = 0i64
;*(v3
+ 3) = 0i64
;}else{v4
= 0i64
;}v5
= 0;if ( input_len
> 0 ){v6
= 0i64
;do{input_copy
= &input
;if ( v39
>= 16 )input_copy
= input
;v8
= &Dst
;if ( qword_140006060
>= 0x10 )v8
= Dst
; v4
[v6
] = input_copy
[v6
] ^ *(v8
+ v5
++ % 27);++v6
;}while ( v5
< input_len
);}arr
[3] = 0i64
;arr
[2] = 0i64
;arr
[1] = 0i64
;arr
[0] = 0i64
;if ( input_len
> 30 ) goto LABEL_28
;v13
= 0;if ( input_len
<= 0 )goto LABEL_28
;v14
= v4
; do {v15
= *v14
+ arr
[3];++v13
;++v14
;switch ( v13
){case 8:arr
[0] = v15
;goto LABEL_24
;case 16:arr
[1] = v15
;goto LABEL_24
;case 24:arr
[2] = v15
;
LABEL_24
:v15
= 0i64
;break;case 32:printf(std
::cout
, "ERRO,out of range");exit(1);break;}arr
[3] = v15
<< 8;}while ( v13
< input_len
);if ( arr
[0] ){v16
= sub_1400024C8(32ui64
);*v16
= arr
[0]; v16
[1] = arr
[1];v16
[2] = arr
[2];v16
[3] = arr
[3];goto LABEL_29
;}
LABEL_28
:v16
= 0i64
;
LABEL_29
:v36
= v16
[2]; v17
= v16
[1]; v18
= *v16
; v19
= sub_14000223C(32ui64
); if ( IsDebuggerPresent() ) {printf(std
::cout
, "Hi , DO not debug me !");Sleep(0x7D0u);exit(0);}v20
= v17
& v18
; *v19
= v17
& v18
; v21
= v36
& ~v18
; v19
[1] = v21
; v22
= ~v17
; v23
= v36
& v22
; v19
[2] = v36
& v22
; v24
= v18
& v22
; v19
[3] = v24
; if ( v21
!= 0x11204161012i64
) {v19
[1] = 0i64
;v21
= 0i64
;}v25
= v21
| v20
| v23
| v24
; v26
= v16
[1]; v27
= v16
[2]; v28
= v23
& *v16
| v27
& (v20
| v26
& ~*v16
| ~(v26
| *v16
));v29
= 0;if ( v28
== 0x8020717153E3013i64
) v29
= v25
== 0x3E3A4717373E7F1Fi64
; if ( (v25
^ v16
[3]) == 0x3E3A4717050F791Fi64
)v0
= v29
; if ( (v21
| v20
| v26
& v27
) != (~*v16
& v27
| 0xC00020130082C0Ci64
) || v0
!= 1 ){printf(std
::cout
, "Wrong answer!try again");j_j_free(v4
);}else{LODWORD(v30
) = printf(std
::cout
, "Congratulations!flag is GXY{");v31
= &input
;if ( v39
>= 16 )v31
= input
;v32
= sub_140001FD0(v30
, v31
, input_len
);printf(v32
, "}");j_j_free(v4
);}
LABEL_45
:if ( v39
>= 0x10 ){v34
= input
;if ( v39
+ 1 >= 0x1000 ){v34
= *(input
- 1);if ( (input
- v34
- 8) > 0x1F )invalid_parameter_noinfo_noreturn();}j_j_free(v34
);}return 0i64
;
}
寫解arr[0~3]的腳本
寫逆異或運算得到flag的腳本,由flag的明文字符串可知,arr[1]的結(jié)果錯誤,原因是原方程組有多組解,參考別的師傅的wp,比賽給出了第二部分的flag,e!P0or_a,替換掉錯誤的8個字符,結(jié)果為We1l_D0ne!P0or_algebra_am_i
總結(jié)
以上是生活随笔為你收集整理的REVERSE-PRACTICE-BUUCTF-13的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。