目录
131_[FlareOn5]FLEGGO
打开附件是个压缩包,再打开是一堆压缩文件。这些文件大小差不多,估计是程序生成的,那么标志估计都是一样。
打开一个找到关键函数发现无法F5
int __cdecl main(int argc, const char **argv, const char **envp)
{
char ArgList[16]; // [esp+0h] [ebp-24h] BYREF
__int128 v5; // [esp+10h] [ebp-14h]
*(_OWORD *)ArgList = 0i64;
v5 = 0i64;
sub_4012D0();
if ( sub_401050() )
{
sub_401510((wchar_t *)L"What is the password?\n", ArgList[0]);
sub_4014C0((wchar_t *)L"%15ls", (char)ArgList); //输入数据
if ( sub_401240(ArgList) ) //检查
{
sub_4010B0(ArgList);
if ( sub_401100() )
{
sub_401510((wchar_t *)L"Everything is awesome!\n", ArgList[0]);
sub_401510((wchar_t *)L"%s => %s\n", (char)&unk_4043A0);
return (unsigned __int16)word_4043CA;
}
else
{
sub_401510((wchar_t *)L"Oh look a rainbow.\n", ArgList[0]);
return -1;
}
}
else
{
sub_401510((wchar_t *)L"Go step on a brick!\n", ArgList[0]); //报错
return -1;
}
}
else
{
sub_401510((wchar_t *)L"I super hate you right now.\n", ArgList[0]);
return -1;
}
}
运行一下,基本确认
C:\buuctf.reverse\131_[FlareOn5]FLEGGO\file>1JpPaUMynR9GflWbxfYvZviqiCB59RcI.exe
What is the password?
oooooooooo
Go step on a brick!
看下汇编
很简单就是输入和一个串比较。由于windows上数据是以UTF-16存放的,所以ASCII码应该是存成A\0B\0这样的格式。输入IconManSucks并不正确,然后瞎找也找不到,看WP说是跟着输入Brick找,找到两个BRICK,,在第2个BRICK后是密码,每个文件位置都相同。在IDA中是看不到的,因为他只出现自己能理解的东西,理解不了的就写成?了。
输入密码后会生成一个图片文件以及一个字母。图片左上角是一个数字
很明显这个数字是这个字母在flag中的位置。将图版排下序然后对照输入字母将其排成flag。由于flag很长所以,只能对图片排序了,不然一会就乱了。
import os
from subprocess import Popen,PIPE
files = os.listdir('./file')
for f in files:
if f[-4:] == '.exe':
data = open("./file/"+f, 'rb').read()[0x2ab0: 0x2ab0+0x20].replace(b'\0',b'')
#print(f, data, end=' ')
p = Popen("./file/"+f, stdin=PIPE, stdout=PIPE)
p.stdin.write(data)
p.stdin.close()
p.stdout.readline()
p.stdout.readline()
msg = p.stdout.readline()
p.stdout.close()
print(f, msg)
#break
#把输入内容整理成文件名:字符 的字典
dit = {
'65141174' : 'w' ,
'85934406' : 'm' ,
'67782682' : 'm' ,
'75072258' : 'r' ,
'16544936' : 'e' ,
'67322218' : '_' ,
'58770751' : 'o' ,
'64915798' : '3' ,
'88763595' : 'e' ,
'18376743' : '_' ,
'36870498' : 'm' ,
'72501159' : 'c' ,
'47619326' : 'p' ,
'70037217' : 'm' ,
'18309310' : '@' ,
'15566524' : 'e' ,
'82100368' : 'm' ,
'60075496' : 's' ,
'71290032' : 'a' ,
'33718379' : '.' ,
'42255131' : 't' ,
'16295588' : 'a' ,
'61333226' : 'f' ,
'13147895' : 'w' ,
'16785906' : '4' ,
'80333569' : 'o' ,
'37723511' : 'n' ,
'44958449' : '_' ,
'30171375' : 's' ,
'72263993' : 'h' ,
'82236857' : 'e' ,
'33098947' : '_' ,
'33662866' : 'r' ,
'47893007' : '_' ,
'61006829' : 'l' ,
'89295012' : '0' ,
'87730986' : '0' ,
'65626704' : '3' ,
'72562746' : '-' ,
'36494753' : '0' ,
'79545849' : 's' ,
'63223880' : 'a' ,
'51227743' : 'a' ,
'73903128' : 'u' ,
'52817899' : 'n' ,
'19343964' : 'o' ,
'12268605' : 's' ,
'47202222' : 'n' }
#将排好序的(文件名前面加序号)文件名dir整理成数组
a = [
'67782682',
'80333569',
'75072258',
'64915798',
'44958449',
'16295588',
'65141174',
'82236857',
'30171375',
'36494753',
'70037217',
'65626704',
'33098947',
'42255131',
'72263993',
'16785906',
'37723511',
'67322218',
'71290032',
'47202222',
'18376743',
'63223880',
'13147895',
'16544936',
'60075496',
'87730986',
'82100368',
'88763595',
'47893007',
'47619326',
'89295012',
'79545849',
'12268605',
'73903128',
'85934406',
'18309310',
'61333226',
'61006829',
'51227743',
'33662866',
'15566524',
'72562746',
'19343964',
'52817899',
'33718379',
'72501159',
'58770751',
'36870498']
flag = ''
for i in a:
flag+=dit[i]
print(flag)
#flag{mor3_awes0m3_th4n_an_awes0me_p0ssum@flare-on.com}
132_[INSHack2018]Tricky-Part2
这个很简单,上来就是对比
__int64 __fastcall check(__int64 a1)
{
int i; // [rsp+1Ch] [rbp-D4h]
int v3[52]; // [rsp+20h] [rbp-D0h]
v3[0] = 73;
v3[1] = 78;
v3[2] = 83;
v3[3] = 65;
v3[4] = 123;
v3[5] = 89;
v3[6] = 48;
v3[7] = 117;
v3[8] = 95;
v3[9] = 115;
v3[10] = 104;
v3[11] = 48;
v3[12] = 117;
v3[13] = 108;
v3[14] = 100;
v3[15] = 95;
v3[16] = 107;
v3[17] = 110;
v3[18] = 48;
v3[19] = 119;
v3[20] = 95;
v3[21] = 116;
v3[22] = 104;
v3[23] = 52;
v3[24] = 116;
v3[25] = 95;
v3[26] = 49;
v3[27] = 95;
v3[28] = 99;
v3[29] = 52;
v3[30] = 110;
v3[31] = 95;
v3[32] = 116;
v3[33] = 114;
v3[34] = 49;
v3[35] = 99;
v3[36] = 107;
v3[37] = 95;
v3[38] = 121;
v3[39] = 48;
v3[40] = 117;
v3[41] = 114;
v3[42] = 95;
v3[43] = 100;
v3[44] = 51;
v3[45] = 98;
v3[46] = 117;
v3[47] = 103;
v3[48] = 103;
v3[49] = 51;
v3[50] = 114;
v3[51] = 125;
for ( i = 0; i <= 51; ++i )
{
if ( *(char *)std::string::operator[](a1, i) != v3[i] )
return 0LL;
}
return 1LL;
}
直接输出就行
a = [73,78,83,65,123,89,48,117,95,115,104,48,117,108,100,95,107,110,48,119,95,116,104,52,116,95,49,95,99,52,110,95,116,114,49,99,107,95,121,48,117,114,95,100,51,98,117,103,103,51,114,125]
print(bytes(a))
#INSA{Y0u_sh0uld_kn0w_th4t_1_c4n_tr1ck_y0ur_d3bugg3r}
#flag{Y0u_sh0uld_kn0w_th4t_1_c4n_tr1ck_y0ur_d3bugg3r}
133_[FlareOn1]5get_it
这个一上来就给每个字符switch调用一个函数
const char *sub_10009EB0()
{
const char *result; // eax
int v1; // [esp+0h] [ebp-8h]
__int16 i; // [esp+4h] [ebp-4h]
for ( i = 8; ; ++i )
{
if ( i > 222 )
return 0;
if ( GetAsyncKeyState(i) == -32767 )
break;
LABEL_2:
;
}
switch ( i )
{
case '\'':
return sub_100093B0();
case '(':
return sub_100093C0();
case ')':
return sub_100093D0();
case '*':
return sub_100093E0();
case '+':
return sub_100093F0();
case ',':
return sub_10009400();
case '-':
return sub_10009410();
case '.':
return sub_10009420();
...
似乎每个函数都一样直接返回字符,一个个点下来还确实有不一样的
const char *sub_10009440()
{
if ( dword_10019460 <= 0 )
{
if ( dword_100194A4 <= 0 )
{
_cfltcvt_init();
}
else
{
dword_100194A4 = 0;
dword_100194A8 = 1;
}
}
else
{
dword_10019460 = 0;
dword_10019464 = 1;
}
return "0";
}
这个函数进行了两次比较。然后一个个点函数,有些1次有些多次,把这些比较放一起
9460,94a4:0
9498,94b0:5
94b4,94c4,94d4:a
94f4:c
9478,948c,94d0,94e8:d
94ac,94cc:e
94bc:f
9464,9468,9474:g
94dc:h
946c:i
94a8:k
7000,94c0:l
94fc:m
9470,94e4:n
947c,9490,94e0,94ec,94f8:o
9488,94a0,94c8:r
94d8:s
9480,9494,949c,94b8,94f0:t
9484:u
似乎flarecom这些都出现了,按时位置进行排序(出现多次的排多次,有重复使用的字符)得到flag,把dot,dash,at改为符号,但怎么也不对。网上搜到u是大写
a = '''
9460,94a4:0
9498,94b0:5
94b4,94c4,94d4:a
94f4:c
9478,948c,94d0,94e8:d
94ac,94cc:e
94bc:f
9464,9468,9474:g
94dc:h
946c:i
94a8:k
7000,94c0:l
94fc:m
9470,94e4:n
947c,9490,94e0,94ec,94f8:o
9488,94a0,94c8:r
94d8:s
9480,9494,949c,94b8,94f0:t
9484:u
'''
dic = {}
a = a.split('\n')
for i in a:
if i == '':
continue
b = i.split(':')
c = b[0].split(',')
for j in c:
dic[j] = b[1]
print(dic)
print(''.join([dic[i] for i in sorted(dic.keys())]))
#l0ggingdoturdot5tr0ke5atflaredashondotcom
#flag{l0gging.ur.5tr0ke5@flare-on.com)
#flag{l0gging.Ur.5tr0ke5@flare-on.com}
134_[NPUCTF2020]芜湖
题目没有输入,运行时输入一首散文诗
眼前重复的风景,
渐渐模糊了约定,
星空下流浪的你,
仍然秘密的距离,
温度消失的瞬间,
无法触摸的明天,
没有引力的世界,
没有脚印的光年,
还在等着你出现,
日日夜夜自转的行星,
到处遮满别人的背影,
让风吹散混乱的呼吸,
快快清醒~
静静照亮原来的自己,
天空洒满忽然的光明,
眼中只要绚烂的天际,
再飞行!
我勇敢地抬起头,
看着茫茫的宇宙,
多少未知的星球,
有没有通向未来路口,
亲爱的伙伴,
让我们一起点燃,
勇气和信念,
在遥远的天边,
银河边缘,
有一片神奇的彩虹海,
和我一起冒险,
飞向另一个世界,
在遥远的天边,
银河边缘,
有一片神奇的彩虹海,
和我一起冒险,
飞向另一个世界,
super magic world~~
用ida打开看就是经过处理以后base64解码然后就输出了
unsigned __int64 o00oo0o0o0o(void)
{
__int64 v0; // rax
bool v2; // [rsp+2h] [rbp-4Eh]
char v3; // [rsp+3h] [rbp-4Dh]
int i; // [rsp+4h] [rbp-4Ch]
int j; // [rsp+8h] [rbp-48h]
int k; // [rsp+Ch] [rbp-44h]
char v7[40]; // [rsp+10h] [rbp-40h] BYREF
unsigned __int64 v8; // [rsp+38h] [rbp-18h]
v8 = __readfsqword(0x28u);
for ( i = 0; i <= 34; ++i )
{
for ( j = 0; j < o000O0ooo0ooOoOo[i]; ++j )
{
v3 = o0ooOo0oo0O[42 * i + j];
v2 = 0;
for ( k = 0; k <= 7; ++k )
v2 = Oo0O((v3 >> (7 - k)) & 1, (97 >> (7 - k)) & 1) ^ (2 * v2);
std::string::operator+=((char *)&oOoOo00[abi:cxx11] + 32 * i, v2);
}
o0o0OO((__int64)v7, (__int64)&oOoOo00[abi:cxx11] + 32 * i);// base64解码
v0 = std::operator<<<char>(&std::cout, v7);
std::ostream::operator<<(v0, &std::endl<char,std::char_traits<char>>);
std::string::~string(v7);
}
std::ostream::operator<<(&std::cout, &std::endl<char,std::char_traits<char>>);
return __readfsqword(0x28u) ^ v8;
}
base64的多句,然后跟进行发现相同的一句许但base64的值不同。应该是base64隐写,网上下个小程序,解下
from pwn import *
data = open('./wuhu', 'rb').read()
def o0o0o(a1, a2):
return (a1 & a2) == 0
def Oo0O(a1, a2):
v2 = o0o0o(a1, a2)
v3 = o0o0o(a1, v2)
v4 = o0o0o(a1, a2)
v5 = o0o0o(a2, v4)
v6 = o0o0o(v5, v3)
return v6
s = ''
for i in range(35):
tmp = ''
for j in range(u32(data[0x46a0 + i*4: 0x46a0 + i*4+4])):
v3 = data[0x40e0 + 42*i + j]
v2 = 0
for k in range(8):
v2 = Oo0O((v3 >> (7 - k)) & 1, (97 >> (7 - k)) & 1) ^ (2 * v2)
tmp += chr(v2)
print(tmp)
s+=tmp+'\n'
open('out1.txt', 'w').write(s)
base64隐写工具
import base64
path = input("请输入加密文件路径\n")
file = open(path)
a = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
aaa = ''
while True:
text = file.readline() # 只读取一行内容
# 判断是否读取到内容
text = text.replace("\n", "")
if not text:
break
if text.count('=') == 1:
aaa = aaa + \
str('{:02b}'.format((a.find(text[len(text)-2])) % 4))
if text.count('=') == 2:
aaa = aaa + \
str('{:04b}'.format((a.find(text[len(text)-3])) % 16))
file.close()
t = ""
ttt = len(aaa)
ttt = ttt//8*8
for i in range(0,ttt,8):
t = t + chr(int( aaa[i:i+8],2))
print(t)
结果
C:\buuctf.reverse\134_[NPUCTF2020]芜湖>py \tools\base64隐写.py
请输入加密文件路径
out1.txt
npuctf{Fly1ng!!!}
135_[FlareOn2]elfie
先用密码flare 解压后,010打开是exe文件MZ 修改扩展名为exe
发现图标是py的文件,用工具解包
py \tools\pyinstxtractor.py elfie.exe
用010打开修改头里发现没有头标记,且文件几乎都是ascii码
把开头和结尾的一点乱码删掉后,把尾部的exec改为print得到py文件
from PySide import QtGui, QtCore
import base64
OOO00O00OO0OO000OOOO00000000OOO0 = ''.join((OOOO00OO0OOO000OOOO00O00O0OOOOOO for OOOO00OO0OOO000OOOO00O00O0OOOOOO in reversed
用到反写这个函数,然后从尾部可以看到反写的flag
class OO00O0O00OOO00OOOO0O00O0000OOOOO(getattr(QtGui, 'tidEtxeTQ'[::-1])):
def __init__(self, OO0O0O0O0OO0OO00000OO00O0O0000O0, OO00O00O00OO00OO0OO0OO000O0O00OO, OO0OOO00O00O0OO00000OO0000OO0OOO):
super(OO00O0O00OOO00OOOO0O00O0000OOOOO, self).__init__(OO0O0O0O0OO0OO00000OO00O0O0000O0)
self.OO0O0O0O0OO0OO00000OO00O0O0000O0 = OO0O0O0O0OO0OO00000OO00O0O0000O0
self.OO00O00O00OO00OO0OO0OO000O0O00OO = OO00O00O00OO00OO0OO0OO000O0O00OO
self.OO0OOO00O00O0OO00000OO0000OO0OOO = OO0OOO00O00O0OO00000OO0000OO0OOO
self.OOOOOOOOOO0O0OOOOO000OO000OO0O00 = False
def O000OOOOOO0OOOO00000OO0O0O000OO0(self):
O0O0O0000OOO000O00000OOO000OO000 = getattr(self, 'txeTnialPot'[::-1])()
if (O0O0O0000OOO000O00000OOO000OO000 == ''.join((OO00O00OOOO00OO000O00OO0OOOO0000 for OO00O00OOOO00OO000O00OO0OOOO0000 in reversed('moc.no-eralf@OOOOY.sev0000L.eiflE')))):
self.OO0O0O0O0OO0OO00000OO00O0O0000O0.setWindowTitle('!sseccus taerg'[::-1])
self.OOOOOOOOOO0O0OOOOO000OO000OO0O00 = True
self.OO0O0O0O0OO0OO00000OO00O0O0000O0.setVisible(False)
self.OO0O0O0O0OO0OO00000OO00O0O0000O0.setVisible(True)
print('moc.no-eralf@OOOOY.sev0000L.eiflE'[::-1])
#flag{Elfie.L0000ves.YOOOO@flare-on.com}