REVERSE-PRACTICE-BUUCTF-27
- [XMAN2018排位赛]Dragon Quest
- [羊城杯 2020]easyre
- [watevrCTF 2019]Repyc
- [2019红帽杯]calc
[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->v40if ( 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数组dov30 = 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);dov26 = 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 ){doindex_ = *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中取一个字节dov22 = y18 < 10 || (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) == 0;while ( y4 >= 10 && (((_BYTE)x3 - 1) * (_BYTE)x3 & 1) != 0 );dov21 = *v23; // v23->v21while ( y18 >= 10 && (((_BYTE)x17 - 1) * (_BYTE)x17 & 1) != 0 );std::vector<int,std::allocator<int>>::vector(v36, v42);// v42赋给v36dov20 = 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处理,返回到v19if ( 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]-nn+=tmpflag+=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(굴)continueelse: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(굴)continueelse:if 굸 == '뗋':if 괠[亀[侰]] > 괠[亀[俴]]:굴 = 궓[亀[佤]]괣.append(굴)continueelse:if 굸 == '똷':if 괠[亀[侰]] == 괠[亀[俴]]:굴 = 亀[佤]괣.append(굴)continueelse:if 굸 == '뚫':if 괠[亀[侰]] == 괠[亀[俴]]:굴 = 괠[亀[佤]]괣.append(굴)continueelse: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}