REVERSE-PRACTICE-BUUCTF-27
[XMAN2018排位赛]Dragon Quest
elf文件,无壳,ida分析
main函数,读取输入,start_quest函数验证输入,根据返回值判断输入是否正确
进入start_quest函数,首先是给hero数组添加元素,检验输入的长度是否为28,输入长度等于28则v7为0,否则v7为1
往下走,由于需要start_quest返回0x1337,则需v7为0,即输入的长度等于28
sanitize_input函数对输入进行检验,由变量值传递可知,sanitize_input函数也要返回0x1337
进入sanitize_input函数,主要的逻辑为,输入进入transform_input函数处理,返回值与hero数组比较
v31 = (char *)std::string::operator[](input, index);// 从input中取一个字节
if ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 )
{
LABEL_71:
if ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 )
goto LABEL_114;
while ( 1 )
{
*(_DWORD *)v40 = *v31;
if ( y4 < 10 || (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) == 0 )
break;
LABEL_114:
*(_DWORD *)v40 = *v31;
}
}
*(_DWORD *)v40 = *v31; // v31->v40
if ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 )
goto LABEL_71;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 )
;
std::vector<int,std::allocator<int>>::push_back(v42, v40);// v40被添加到v42数组
do
v30 = y18 < 10 || (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) == 0;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 );
if ( !v30 )
LABEL_74:
*v37 = *v41;
if ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 )
LABEL_99:
*v37 = *v41;
v1 = v37;
*v37 = *v41;
v29 = *v1;
v28 = y18 < 10 || (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) == 0;
if ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 )
goto LABEL_99;
if ( !v28 )
goto LABEL_74;
v27 = std::string::length(input);
do
v26 = y18 < 10 || (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) == 0;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 );
if ( !v26 )
LABEL_75:
*v37 = (v27 >> 40) & v29 | 0x1C;
v2 = v37;
*v37 = (v27 >> 40) & v29 | 0x1C;
v25 = *v2 != 0;
if ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 )
goto LABEL_75;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 )
;
if ( v25 )
{
do
index_ = *v41;
while ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 );
v23 = (int *)std::vector<int,std::allocator<int>>::operator[]((unsigned int)&hero, index_);// 从hero中取一个字节
do
v22 = y18 < 10 || (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) == 0;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 );
do
v21 = *v23; // v23->v21
while ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 );
std::vector<int,std::allocator<int>>::vector(v36, v42);// v42赋给v36
do
v20 = y18 < 10 || (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) == 0;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 );
while ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 )
;
while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 )
;
v19 = transform_input(v36); // 对v36处理,返回到v19
if ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 )
goto LABEL_79;
while ( 1 )
{
v18 = v21 == v19; // v19与v21比较
进入transform_input函数,主要的逻辑为,取出输入的一个字节input[i],v16初始值为0,v16每次加上input[i],然后返回v16,与hero数组的元素比较
已知hero数组,写逆运算脚本即可得到flag
hero=[0x64,0xd6,0xa,0x71,0xa1,0xf,0x6e,0xdd,0x4f,0xae,
0x1e,0x52,0xc6,0x38,0xa1,0x4,0x35,0x96,0x4,0x63,
0xcc,0x40,0x75,0xd4,0x20,0x6c,0xc2,0xf]
n=0
flag=""
for i in range(len(hero)):
tmp=hero[i]-n
n+=tmp
flag+=chr(tmp%128)
print(flag)
#dr4g0n_or_p4tric1an_it5_LLVM
[羊城杯 2020]easyre
exe程序,运行后输入,无壳,ida分析
main函数,读取输入,检验输入的长度是否为38,对输入进行三次变换,最后与Str2比较
三次变换都很容易理解,分别是常规base64,分组换位置,以及类似凯撒的右移三位
写逆运算脚本即可得到flag
import base64
str2="EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG"
data=[]
for c in str2:
if c.isdigit():
data.append((ord(c)-48-3)%10+48)
elif c.isupper():
data.append((ord(c)-65 - 3) % 26 + 65)
elif c.islower():
data.append((ord(c)-97 - 3) % 26 + 97)
else:
data.append(ord(c))
flag=[0]*len(data)
flag[0:13]=data[13:26]
flag[13:26]=data[39:len(data)]
flag[26:39]=data[0:13]
flag[39:len(flag)]=data[26:39]
print(base64.b64decode(''.join(chr(i) for i in flag)))
# GWHT{672cc4778a38e80cb362987341133ea2}
[watevrCTF 2019]Repyc
.pyc文件,用uncompyle6反编译得到源代码,python2会检测为非ascii码,换成python3即可
佤 = 0
侰 = ~佤 * ~佤
俴 = 侰 + 侰
def 䯂(䵦):
굴 = 佤
굿 = 佤
괠 = [佤] * 俴 ** (俴 * 俴)
궓 = [佤] * 100
괣 = []
while 䵦[굴][佤] != '듃':
굸 = 䵦[굴][佤].lower()
亀 = 䵦[굴][侰:]
if 굸 == '뉃':
괠[亀[佤]] = 괠[亀[侰]] + 괠[亀[俴]]
else:
if 굸 == '렀':
괠[亀[佤]] = 괠[亀[侰]] ^ 괠[亀[俴]]
else:
if 굸 == '렳':
괠[亀[佤]] = 괠[亀[侰]] - 괠[亀[俴]]
else:
if 굸 == '냃':
괠[亀[佤]] = 괠[亀[侰]] * 괠[亀[俴]]
else:
if 굸 == '뢯':
괠[亀[佤]] = 괠[亀[侰]] / 괠[亀[俴]]
else:
if 굸 == '륇':
괠[亀[佤]] = 괠[亀[侰]] & 괠[亀[俴]]
else:
if 굸 == '맳':
괠[亀[佤]] = 괠[亀[侰]] | 괠[亀[俴]]
else:
if 굸 == '괡':
괠[亀[佤]] = 괠[亀[佤]]
else:
if 굸 == '뫇':
괠[亀[佤]] = 괠[亀[侰]]
else:
if 굸 == '꼖':
괠[亀[佤]] = 亀[侰]
else:
if 굸 == '뫻':
궓[亀[佤]] = 괠[亀[侰]]
else:
if 굸 == '딓':
괠[亀[佤]] = 궓[亀[侰]]
else:
if 굸 == '댒':
괠[亀[佤]] = 佤
else:
if 굸 == '묇':
궓[亀[佤]] = 佤
else:
if 굸 == '묟':
괠[亀[佤]] = input(괠[亀[侰]])
else:
if 굸 == '꽺':
궓[亀[佤]] = input(괠[亀[侰]])
else:
if 굸 == '돯':
print(괠[亀[佤]])
else:
if 굸 == '뭗':
print(궓[亀[佤]])
else:
if 굸 == '뭿':
굴 = 괠[亀[佤]]
else:
if 굸 == '뮓':
굴 = 궓[亀[佤]]
else:
if 굸 == '뮳':
굴 = 괣.pop()
else:
if 굸 == '믃':
if 괠[亀[侰]] > 괠[亀[俴]]:
굴 = 亀[佤]
괣.append(굴)
continue
else:
if 굸 == '꽲':
괠[7] = 佤
for i in range(len( 괠[亀[佤]])):
if 괠[亀[佤]] != 괠[亀[侰]]:
괠[7] = 侰
굴 = 괠[亀[ 俴]]
괣.append(굴)
else:
if 굸 == '꾮':
괢 = ''
for i in range(len(괠[亀[佤]])):
괢 += chr(ord(괠[亀[佤]][i]) ^ 괠[亀[侰]])
괠[亀[佤]] = 괢
else:
if 굸 == '꿚':
괢 = ''
for i in range(len(괠[亀[佤]])):
괢 += chr(ord(괠[亀[佤]][i]) - 괠[亀[侰]])
괠[亀[佤]] = 괢
else:
if 굸 == '떇':
if 괠[亀[侰]] > 괠[亀[俴]]:
굴 = 괠[亀[佤]]
괣.append(굴)
continue
else:
if 굸 == '뗋':
if 괠[亀[侰]] > 괠[亀[俴]]:
굴 = 궓[亀[佤]]
괣.append(굴)
continue
else:
if 굸 == '똷':
if 괠[亀[侰]] == 괠[亀[俴]]:
굴 = 亀[佤]
괣.append(굴)
continue
else:
if 굸 == '뚫':
if 괠[亀[侰]] == 괠[亀[俴]]:
굴 = 괠[亀[佤]]
괣.append(굴)
continue
else:
if 굸 == '띇':
if 괠[亀[侰]] == 괠[亀[俴]]:
굴 = 궓[亀[佤]]
괣.append(굴)
continue
굴 += 侰
䯂([
[
'꼖', 佤, 'Authentication token: '],
[
'꽺', 佤, 佤],
[
'꼖', 6, 'á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'],
[
'꼖', 俴, 俴 ** (3 * 俴 + 侰) - 俴 ** (俴 + 侰)],
[
'꼖', 4, 15],
[
'꼖', 3, 侰],
[
'냃', 俴, 俴, 3],
[
'뉃', 俴, 俴, 4],
[
'괡', 佤, 俴],
[
'댒', 3],
[
'꾮', 6, 3],
[
'꼖', 佤, 'Thanks.'],
[
'꼖', 侰, 'Authorizing access...'],
[
'돯', 佤],
[
'딓', 佤, 佤],
[
'꾮', 佤, 俴],
[
'꿚', 佤, 4],
[
'꼖', 5, 19],
[
'꽲', 佤, 6, 5],
[
'돯', 侰],
[
'듃'],
[
'꼖', 侰, 'Access denied!'],
[
'돯', 侰],
[
'듃']])
运行后输入,调试发现,对输入的处理很简单,input[i]=((input[i])^135)-15,即输入先异或135,再减去15,最后和那段长字符串比较,写脚本即可得到flag
res="á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë"
flag=""
for c in res:
flag+=chr((ord(c)+15)^135)
print(flag)
#watevr{this_must_be_the_best_encryption_method_evr_henceforth_this_is_the_new_Advanced_Encryption_Stand¨ard_anyways_i_dont_really_have_a_good_vid_but_i_really_enjoy_this_song_i_hope_you_will_enjoy_it_aswell!_youtube.com/watch?v=E5yFcdPAGv0}
[2019红帽杯]calc
exe程序,运行后输入,无壳,ida分析
三次输入,对输入一顿运算,没看懂
参考网上别的师傅的wp,2019红帽杯 Writeup by X1cT34m
原来是在满足input_2<input_1<input_3的条件下,得到input_1**3+input_2**3+input_2**3==42
,即三个整数的立方和等于42
百度一下,果然有解
(-80538738812075974)**3 + 80435758145817515**3 + 12602123297335631**3==42
将程序的三个sleep函数patch掉,按input_2<input_1<input_3的条件输入,得到flag
import hashlib
flag="flag{"
s="804357581458175151260212329733563180538738812075974"
h=hashlib.md5()
h.update(s.encode(encoding='utf-8'))
flag+=h.hexdigest()
flag+="}"
print(flag)
# flag{951e27be2b2f10b7fa22a6dc8f4682bd}