生活随笔
收集整理的這篇文章主要介紹了
REVERSE-PRACTICE-BUUCTF-15
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
REVERSE-PRACTICE-BUUCTF-15
- [2019紅帽杯]xx
- [ACTF新生賽2020]Universe_final_answer
- [WUSTCTF2020]level4
- findKey
[2019紅帽杯]xx
exe程序,運行后直接輸入,無殼,ida分析
交叉引用字符串“You win!”來到sub_1400011A0函數
主要的邏輯為
讀取輸入,驗證輸入長度是否為19,且均為小寫字母或0~9的數字
對輸入進行TEA加密,加密密鑰通過調試可知是輸入的前4個字符,即“flag”
TEA加密的密文變換位置
變換位置后的密文循環異或
循環異或后的密文與已知字節比較
__int64 __fastcall
sub_1400011A0(__int64 a1
, __int64 a2
)
{unsigned __int64 input_len_
; signed __int64 input_len
; __int128
*v4
; __int64 Code
; __int128
*v6
; int v7
; __int128
*v8
; char v9
; int v10
; __int64 v11
; unsigned __int64 Code_len
; signed __int64 Code_len_
; unsigned __int64 v14
; unsigned __int64 i
; _BYTE
*cipher
; size_t v17
; _BYTE
*cipher_
; _BYTE
*v19
; signed int v20
; char *v21
; signed __int64 v22
; char v23
; signed __int64 v24
; signed __int64 v25
; __int64 v26
; size_t Size
; __int128 v29
; int v30
; int v31
; int input
[4]; int v33
; *(_OWORD
*)input
= 0i64
;v33
= 0;sub_1400018C0(std
::cin
, a2
, input
); input_len_
= -1i64
;input_len
= -1i64
;do ++input_len
;while ( *((_BYTE
*)input
+ input_len
) );if ( input_len
!= 19 ) {sub_140001620(std
::cout
, "error\n");_exit((unsigned __int64
)input
);}v4
= (__int128
*)sub_140001E5C(5ui64
);Code
= *(_QWORD
*)&::Code
; v6
= v4
;v7
= 0;v8
= v4
; do{v9
= *((_BYTE
*)v8
+ (char *)input
- (char *)v4
);v10
= 0;*(_BYTE
*)v8
= v9
;v11
= 0i64
;Code_len
= -1i64
;do++Code_len
;while ( *(_BYTE
*)(Code
+ Code_len
) );if ( Code_len
){do{if ( v9
== *(_BYTE
*)(Code
+ v11
) )break;++v10
;++v11
;}while ( v10
< Code_len
);}Code_len_
= -1i64
;do++Code_len_
;while ( *(_BYTE
*)(Code
+ Code_len_
) );if ( v10
== Code_len_
) _exit(Code
);v8
= (__int128
*)((char *)v8
+ 1);}while ( (char *)v8
- (char *)v4
< 4 );*((_BYTE
*)v4
+ 4) = 0;do++input_len_
;while ( *((_BYTE
*)input
+ input_len_
) );v14
= 0i64
;v29
= *v6
;while ( *((_BYTE
*)&v29
+ v14
) ){if ( !*((_BYTE
*)&v29
+ v14
+ 1) ){++v14
;break;}if ( !*((_BYTE
*)&v29
+ v14
+ 2) ){v14
+= 2i64
;break;}if ( !*((_BYTE
*)&v29
+ v14
+ 3) ){v14
+= 3i64
;break;}v14
+= 4i64
;if ( v14
>= 0x10 )break;}for ( i
= v14
+ 1; i
< 16; ++i
)*((_BYTE
*)&v29
+ i
) = 0;cipher
= sub_140001AB0((__int64
)input
, input_len_
, (unsigned __int8
*)&v29
, &Size
);v17
= Size
;cipher_
= cipher
;v19
= sub_140001E5C(Size
);v20
= 1;*v19
= cipher_
[2]; v21
= v19
+ 1;v19
[1] = *cipher_
;v19
[2] = cipher_
[3];v19
[3] = cipher_
[1];v19
[4] = cipher_
[6];v19
[5] = cipher_
[4];v19
[6] = cipher_
[7];v19
[7] = cipher_
[5];v19
[8] = cipher_
[10];v19
[9] = cipher_
[8];v19
[10] = cipher_
[11];v19
[11] = cipher_
[9];v19
[12] = cipher_
[14];v19
[13] = cipher_
[12];v19
[14] = cipher_
[15];v19
[15] = cipher_
[13];v19
[16] = cipher_
[18];v19
[17] = cipher_
[16];v19
[18] = cipher_
[19];v19
[19] = cipher_
[17];v19
[20] = cipher_
[22];v19
[21] = cipher_
[20];v19
[22] = cipher_
[23];for ( v19
[23] = cipher_
[21]; v20
< v17
; ++v21
){v22
= 0i64
;if ( v20
/ 3 > 0 ) {v23
= *v21
; do{v23
^= v19
[v22
++]; *v21
= v23
;}while ( v22
< v20
/ 3 );}++v20
;}*(_QWORD
*)&v29
= 0xC0953A7C6B40BCCEi64
; v24
= v19
- (_BYTE
*)&v29
;*((_QWORD
*)&v29
+ 1) = 0x3502F79120209BEFi64
;v25
= 0i64
;v30
= 0xC8021823;v31
= 0xFA5656E7;do{if ( *((_BYTE
*)&v29
+ v25
) != *((_BYTE
*)&v29
+ v25
+ v24
) )_exit(v7
* v7
);++v7
;++v25
;}while ( v25
< 24 );v26
= sub_140001620(std
::cout
, "You win!");std
::basic_ostream
<char,std
::char_traits
<char>>::operator
<<(v26
, sub_1400017F0
);return 0i64
;
}
先寫逆循環異或和逆位置變換得到TEA加密的密文腳本
網上找的xxtea的python代碼,參考:XXTEA 加解密 as3 和 Python 分別實現
密鑰為“flag”需要加長到16,寫解xxtea腳本即可得到flag
import struct_DELTA
= 0x9E3779B9def _long2str(v
, w
):n
= (len(v
) - 1) << 2if w
:m
= v
[-1]if (m
< n
- 3) or (m
> n
): return ''n
= ms
= struct
.pack
('<%iL' % len(v
), *v
)return s
[0:n
] if w
else s
def _str2long(s
, w
):n
= len(s
)m
= (4 - (n
& 3) & 3) + ns
= s
.ljust
(m
, "\0")v
= list(struct
.unpack
('<%iL' % (m
>> 2), s
))if w
: v
.append
(n
)return v
def encrypt(str, key
):if str == '': return strv
= _str2long
(str, True)k
= _str2long
(key
.ljust
(16, "\0"), False)n
= len(v
) - 1z
= v
[n
]y
= v
[0]sum = 0q
= 6 + 52 // (n
+ 1)while q
> 0:sum = (sum + _DELTA
) & 0xffffffffe
= sum >> 2 & 3for p
in range(n
):y
= v
[p
+ 1]v
[p
] = (v
[p
] + ((z
>> 5 ^ y
<< 2) + (y
>> 3 ^ z
<< 4) ^ (sum ^ y
) + (k
[p
& 3 ^ e
] ^ z
))) & 0xffffffffz
= v
[p
]y
= v
[0]v
[n
] = (v
[n
] + ((z
>> 5 ^ y
<< 2) + (y
>> 3 ^ z
<< 4) ^ (sum ^ y
) + (k
[n
& 3 ^ e
] ^ z
))) & 0xffffffffz
= v
[n
]q
-= 1return _long2str
(v
, False)def decrypt(str, key
):if str == '': return strv
= _str2long
(str, False)k
= _str2long
(key
.ljust
(16, "\0"), False)n
= len(v
) - 1z
= v
[n
]y
= v
[0]q
= 6 + 52 // (n
+ 1)sum = (q
* _DELTA
) & 0xffffffffwhile (sum != 0):e
= sum >> 2 & 3for p
in range(n
, 0, -1):z
= v
[p
- 1]v
[p
] = (v
[p
] - ((z
>> 5 ^ y
<< 2) + (y
>> 3 ^ z
<< 4) ^ (sum ^ y
) + (k
[p
& 3 ^ e
] ^ z
))) & 0xffffffffy
= v
[p
]z
= v
[n
]v
[0] = (v
[0] - ((z
>> 5 ^ y
<< 2) + (y
>> 3 ^ z
<< 4) ^ (sum ^ y
) + (k
[0 & 3 ^ e
] ^ z
))) & 0xffffffffy
= v
[0]sum = (sum - _DELTA
) & 0xffffffffreturn _long2str
(v
, True)def xor(x
,y
):return ord(x
) ^ ord(y
)key
="flag"+'\x00'*12
cipher_data
=['\xbc','\xa5','\xce','\x40','\xf4','\xb2','\xb2','\xe7','\xa9','\x12','\x9d','\x12','\xae','\x10','\xc8','\x5b','\x3d','\xd7','\x06','\x1d','\xdc','\x70','\xf8','\xdc']
cipher
=''.join
(cipher_data
)
print(decrypt
(cipher
,key
))
[ACTF新生賽2020]Universe_final_answer
elf文件,無殼,ida分析
main函數,讀取輸入,check函數驗證輸入的字符,輸入驗證成功,程序調用sub_C50,最后輸出flag
重要的是check函數,分析可知,驗證input的字符,就是驗證方程組是否成立
利用python的z3庫寫腳本得到input
from z3
import *
flag
=[Int
('flag[%d]' %i
) for i
in range(10)]
s
=Solver
()
s
.add
(-85 * flag
[8] + 58 * flag
[7] + 97 * flag
[6] + flag
[5] + -45 * flag
[4] + 84 * flag
[3] + 95 * flag
[0] - 20 * flag
[1] + 12 * flag
[2] == 12613)
s
.add
(30 * flag
[9] + -70 * flag
[8] + -122 * flag
[6] + -81 * flag
[5] + -66 * flag
[4] + -115 * flag
[3] + -41 * flag
[2] + -86 * flag
[1] - 15 * flag
[0] - 30 * flag
[7] == -54400)
s
.add
(-103 * flag
[9] + 120 * flag
[7] + 108 * flag
[5] + 48 * flag
[3] + -89 * flag
[2] + 78 * flag
[1] - 41 * flag
[0] + 31 * flag
[4] - (flag
[6]*64) - 120 * flag
[8] == -10283)
s
.add
(71 * flag
[6] + (flag
[5] *128) + 99 * flag
[4] + -111 * flag
[2] + 85 * flag
[1] + 79 * flag
[0] - 30 * flag
[3] - 119 * flag
[7] + 48 * flag
[8] - 16 * flag
[9] == 22855)
s
.add
(5 * flag
[9] + 23 * flag
[8] + 122 * flag
[7] + -19 * flag
[6] + 99 * flag
[5] + -117 * flag
[4] + -69 * flag
[2] + 22 * flag
[1] - 98 * flag
[0] + 10 * flag
[3] == -2944)
s
.add
(-54 * flag
[9] + -23 * flag
[7] + -82 * flag
[2] + -85 * flag
[0] + 124 * flag
[1] - 11 * flag
[3] - 8 * flag
[4] - 60 * flag
[5] + 95 * flag
[6] + 100 * flag
[8] == -2222)
s
.add
(-83 * flag
[9] + -111 * flag
[5] + -57 * flag
[0] + 41 * flag
[1] + 73 * flag
[2] - 18 * flag
[3] + 26 * flag
[4] + 16 * flag
[6] + 77 * flag
[7] - 63 * flag
[8] == -13258)
s
.add
(81 * flag
[9] + -48 * flag
[8] + 66 * flag
[7] + -104 * flag
[6] + -121 * flag
[5] + 95 * flag
[4] + 85 * flag
[3] + 60 * flag
[2] + -85 * flag
[0] + 80 * flag
[1] == -1559)
s
.add
(101 * flag
[9] + -85 * flag
[8] + 7 * flag
[6] + 117 * flag
[5] + -83 * flag
[4] + -101 * flag
[3] + 90 * flag
[2] + -28 * flag
[1] + 18 * flag
[0] - flag
[7] == 6308 )
s
.add
(99 * flag
[9] + -28 * flag
[8] + 5 * flag
[7] + 93 * flag
[6] + -18 * flag
[5] + -127 * flag
[4] + 6 * flag
[3] + -9 * flag
[2] + -93 * flag
[1] + 58 * flag
[0] == -1697)
if s
.check
()==sat
:print(s
.model
())
運行結果
轉成字符串,運行elf文件,輸入,得到flag
[WUSTCTF2020]level4
elf文件,運行后輸出了幾段字符串,可知是二叉樹的遍歷,無殼,ida分析
main函數,程序輸出的type1為中序遍歷,type2為后序遍歷,type3被注釋掉,應該是先序遍歷
中序遍歷:2f0t02T{hcsiI_SwA__r7Ee}
后序遍歷:20f0Th{2tsIS_icArE}e7__w
由中序遍歷和后序遍歷的字符串確定二叉樹,再先序遍歷二叉樹,即為flag
代碼參考:已知后序序遍歷序列和中序遍歷序列建立二叉樹
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char ElementType
;
typedef struct BiTNode
{ElementType data
;struct BiTNode
* lchild
;struct BiTNode
* rchild
;
}BiTNode
, *BiTree
;BiTree
CreatBinTree(char* post
, char* in
, int n
);
void preorder(BiTree T
);int main()
{BiTree T
;char postlist
[100] = "20f0Th{2tsIS_icArE}e7__w";char inlist
[100] = "2f0t02T{hcsiI_SwA__r7Ee}";int length
;length
= strlen(postlist
);T
= CreatBinTree(postlist
, inlist
, length
);preorder(T
);return 0;
}
void preorder(BiTree T
)
{if (T
){printf("%c", T
->data
);preorder(T
->lchild
);preorder(T
->rchild
);}
}
BiTree
CreatBinTree(char* post
, char* in
, int n
)
{BiTree T
;int i
;if (n
<= 0) return NULL;T
= (BiTree
)malloc(sizeof(BiTNode
));T
->data
= post
[n
- 1];for (i
= 0; in
[i
] != post
[n
- 1]; i
++);T
->lchild
= CreatBinTree(post
, in
, i
);T
->rchild
= CreatBinTree(post
+ i
, in
+ i
+ 1, n
- 1 - i
);return T
;
}
運行結果即為flag
findKey
exe程序,無殼,ida分析
交叉引用字符串“flag{}”,發現從地址0x00401640開始,代碼就沒有被ida識別,應該是加了花指令
在地址0x00401918和地址0x0040191D處,兩條一樣的指令,放在了一起,nop掉第二條push指令
在地址0x00401640處右鍵->create function,或者選中全部的紅色地址代碼,按p創建函數,F5反匯編
主要的邏輯為
v20的字符串和v16的字符串循環異或,結果和pbData的md5散列值比較
比較相等時,md5散列前的pbData和unk_423030循環異或,結果即為flag
LRESULT __stdcall
sub_401640(HWND hWndParent
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
{int v5
; size_t v6
; DWORD v7
; int v8
; int v9
; const char *v10
; CHAR
*v11
; int v12
; int v13
; UINT v14
; CHAR v15
; CHAR v16
[2]; int v17
; __int16 v18
; char v19
; char v20
; char v21
; __int16 v22
; char v23
; CHAR v24
; CHAR String
[4]; int v26
; __int16 v27
; CHAR Text
; struct tagRECT Rect
; CHAR Buffer
; HDC hdc
; struct tagPAINTSTRUCT Paint
; WPARAM v33
; int v34
; LoadStringA(hInstance
, 0x6Au, &Buffer
, 100);v14
= Msg
;if ( Msg
> 0x111 ){if ( v14
== 517 ){if ( strlen((const char *)&pbData
) > 6 )ExitProcess(0);if ( strlen((const char *)&pbData
) ){memset(&v24
, 0, 0x100u);v6
= strlen((const char *)&pbData
);memcpy(&v24
, &pbData
, v6
); v10
= (const char *)&pbData
;do{v7
= strlen(v10
);sub_40101E(&pbData
, v7
, v11
); }while ( &v12
&& !&v12
);strcpy(&v20
, "0kk`d1a`55k222k2a776jbfgd`06cjjb");memset(&v21
, 0, 0xDCu);v22
= 0;v23
= 0;strcpy(v16
, "SS"); v17
= 0;v18
= 0;v19
= 0;v8
= strlen(&v20
);sub_401005(v16
, (int)&v20
, v8
); if ( _strcmpi((const char *)&pbData
, &v20
) ){SetWindowTextA(hWndParent
, "flag{}");MessageBoxA(hWndParent
, "Are you kidding me?", "^_^", 0);ExitProcess(0);}memcpy(&v15
, &unk_423030
, 0x32u); v9
= strlen(&v15
);sub_401005(&v24
, (int)&v15
, v9
); MessageBoxA(hWndParent
, &v15
, 0, 0x32u);}++dword_428D54
;}else{if ( v14
!= 520 )return DefWindowProcA(hWndParent
, Msg
, wParam
, lParam
);if ( dword_428D54
== 16 ){strcpy(String
, "ctf");v26
= 0;v27
= 0;SetWindowTextA(hWndParent
, String
);strcpy(&Text
, "Are you kidding me?");MessageBoxA(hWndParent
, &Text
, &Buffer
, 0);}++dword_428D54
;}}else{switch ( v14
){case 0x111u:v34
= (unsigned __int16
)wParam
;v33
= wParam
>> 16;v13
= (unsigned __int16
)wParam
;if ( (unsigned __int16
)wParam
== 104 ){DialogBoxParamA(hInstance
, (LPCSTR
)0x67, hWndParent
, (DLGPROC
)DialogFunc
, 0);}else{if ( v13
!= 105 )return DefWindowProcA(hWndParent
, Msg
, wParam
, lParam
);DestroyWindow(hWndParent
);}break;case 2u:PostQuitMessage(0);break;case 0xFu:hdc
= BeginPaint(hWndParent
, &Paint
);GetClientRect(hWndParent
, &Rect
);v5
= strlen(&Buffer
);DrawTextA(hdc
, &Buffer
, v5
, &Rect
, 1u);EndPaint(hWndParent
, &Paint
);break;default:return DefWindowProcA(hWndParent
, Msg
, wParam
, lParam
);}}return 0;
}
先寫腳本得到pbData的md5散列值,通過在線網站求逆
再寫md5散列前的pbData(v24)和unk_unk_423030(v15)循環異或的腳本,得到flag
總結
以上是生活随笔為你收集整理的REVERSE-PRACTICE-BUUCTF-15的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。