999 ——> y
88 ——> u
777 ——> r
6 ——> m
4 ——> g
777 ——> r
333 ——> f
444 ——> i
66 ——> n
7777 ——> s
666 ——> o
2 ——> a
33 ——> e
999 ——> y
4444 ——> i
555 ——> l
777 ——> r
33 ——> e
3 ——> d
打开压缩包得到一张图片和TXT文件,图片是个公众号无其他有效提示,打开文件得到很多base64,base64隐写,参考大佬脚本
abs() :返回数字的绝对值
index() :从列表中找出某个值第一个匹配项的索引位置
readlines():方法用于读取所有行
bin():返回一个整数 int 或者长整数 long int 的二进制表示
# encoding:utf-8
def get_base64_diff_value(s1, s2):
base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
res = 0
for i in xrange(len(s2)):
if s1[i] != s2[i]:
return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
return res
def solve_stego():
with open('ComeOn!.txt', 'rb') as f:
file_lines = f.readlines()
bin_str = ''
for line in file_lines:
steg_line = line.replace('\n', '')
norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
diff = get_base64_diff_value(steg_line, norm_line)
print diff
pads_num = steg_line.count('=')
if diff:
bin_str += bin(diff)[2:].zfill(pads_num * 2)
else:
bin_str += '0' * pads_num * 2
print goflag(bin_str)
def goflag(bin_str):
res_str = ''
for i in xrange(0, len(bin_str), 8):
res_str += chr(int(bin_str[i:i + 8], 2))
return res_str
if __name__ == '__main__':
solve_stego()
参考:
https://daidr.me/archives/code-585.html
https://blog.csdn.net/qq_43431158/article/details/109525795
https://blog.csdn.net/Sanctuary1307/article/details/113820321
https://blog.csdn.net/Sanctuary1307/article/details/113836907
概述:
用64个ascii字符作为基础来编码二进制内容的一种编码方式。
base64将3个字节(24位)作为一组进行处理。不足3字节时填充0,并在结尾使用 =
来标识填充的字节数。并将每6位作为1小组,将24位编码成4组6位二进制。此时,这6位二进制一共有2的六次方即64种情况,正好能够用64个字符来表示。(因此编码完后体积会增大1/3)
Example:
将待解码字符串中的字符对应查找Base64编码表中的序列值(末尾的“=”直接忽略)
将所得对应序列值转换为6位二进制字串
将所有6位二进制字串按8位分割
将每个8位二进制字串转换为十进制
十进制值对应的ASCII字符串即为结果
Example:
概述:
在对长度非3的倍数的字符串进行Base64编码过程中,进行转换为二进制字串这一步骤会在末尾添加0,而解码过程中之前添加的0则会被舍弃。
而base64隐写产生的原因就在于,添加的0字符在进行base64解码时会被舍弃,这意味着在这一步骤添加的二进制值可以不全为0,这并不影响解码结果。
Example:
Terra
这一字符串的长度为5,非3的倍数,在转为6位二进制字串时添加了两个0(红色加粗部分)。编码后的结果为VGVycmE=
:
倘若添加的二进制值不全为0,虽然会改变“=”号前最后一个字符的值,使编码后的字符串变为VGVycmH=
。但该字符串进行Base64解码的结果依然是Terra
:
末尾有两个“=”字符的编码字符串同样如此,Lucy
字符串正常编码应为THVjeQ==
:
修改后为THVjeV==
,同上,进行base64解码结果依然是Lucy
若像这样对多个base64编码字符串结尾进行修改,即可隐藏更多的信息,这就是base64隐写。
常见的Base64隐写题为一个txt文本文档,内含多个经过base64编码的字符串。解码规则是将所有被修改过的base64字符串结尾的二进制值提取出来组成一个二进制串,以8位分割并转为十进制值,最终十进制对应的ASCII字符串即为base64隐写结果。
strip:方法用于移除字符串头尾指定的字符(默认为空格)或字符序列
# 提取
def base64value(c):
table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
for i in range(64):
if table[i] == c:
return i
return 0
# 分割
def base64stego():
f = open("xxx.txt","rb")
lines = f.readlines()
x = ''
for line in lines:
l = str(line, encoding = "utf-8").strip()
if l[-1] == '=':
if l[-2] == '=':
x += bin(base64value(l[-3]))[-4:]
else:
x += bin(base64value(l[-2]))[-2:]
flag = ''
for i in range(0, len(x), 8):
flag += chr(int(x[i:i+8],2))
print(flag)
if __name__ == '__main__':
base64stego()
打开压缩包得到一个需要解密的文件和一个提示txt
使用010的EBCDIC编码即可得到压缩密码
https://zhuanlan.zhihu.com/p/27053660
为了在计算机上存储、处理文字等字符,就必须将这些字符转换成二进制数字,于是为了统一转换标准设计了字符编码标准
最开始设计出来的字符编码标准是EBCDIC编码标准。EBCDIC(扩展二进制编码的十进制交换码)的缩写。
EBCDIC码是由国际商用机器公司(即IBM)为大型机操作系统而开发设计的,于1964年推出。
在EBCDIC码中,英文字母不是连续排列的,中间出现多次断续,这带来了一些困扰和麻烦。
因此,在后来IBM的个人计算机和工作站操作系统中并没有采用EBCDIC码,而是采用了晚于EBCDIC码推出、且后来成为了英文字符编码工业标准的ASCII编码方案
ASCII字符编码
ASCII码的编码方式参照了EBCDIC码,并吸取了其经验教训,将英文字母进行了连续排列,这方便了程序处理。
ASCII码使用七个二进制数字(即比特)来表示一个字符,总共表示128个字符(2^7 = 128,二进制编码为0000 0000 ~ 0111 1111,对应的十进制就是0~127)。
由于目前计算机普遍采用8位作为一个字节来进行存取与处理,因此剩下最高位的那1比特一般为0,但有时在一些通讯系统中也被用作奇偶校验位。
通过密码解压得到一堆图片,是福尔摩斯小人密码
对照密码表按照图片名称顺序即可得到flag
打开题目给的TXT文件发现很像文件的十六进制,导入010查看一下,发现是一个rar文件
将文件另存为rar得到一个加密的压缩包,无任何提示,先尝试四位纯数字爆破
得到一张无法打开的图片,放入010查看
校验发现不是PNG文件,既然文件头有问题,尝试看一下文件尾FF D9
明显是JPG文件尾(PNG文件尾:AE 42 60 82
),于是修改文件头为FF D8 FF
题目给出的压缩包无法打开,使用010查看文件
发现文件头格式顺序错误,RAR的文件头为52 61 72 21 1A 07 00
(文件尾一般为C4 3D 7B 00 40 07 00
)
正常打开后得到一个Word文档,打开后没有有效信息
尝试用formost提取,得到很多文件
在document.xml文件中发现一串奇怪的音符
使用音符在线解密即可
♭♯♪‖¶♬♭♭♪♭‖‖♭♭♬‖♫♪‖♩♬‖♬♬♭♭♫‖♩♫‖♬♪♭♭♭‖¶∮‖‖‖‖♩♬‖♬♪‖♩♫♭♭♭♭♭§‖♩♩♭♭♫♭♭♭‖♬♭‖¶§♭♭♯‖♫∮‖♬¶‖¶∮‖♬♫‖♫♬‖♫♫§=
题目提示凯撒加密,尝试用大佬的穷举脚本跑一下
# 位移
def change(c,i):
num=ord(c)
if(num>=33 and num<=126):
num=33+(num+i-33)%(94) #126-33=93
return chr(num)
# 加密
def kaisa_jiAmi(string,i):
string_new=''
for s in string:
string_new+=change(s,i)
print(string_new)
return string_new
# 解密
def kaisa_jiEmi(string):
for i in range(0,94):
print('第'+str(i+1)+'种可能:',end=' ')
#区别在于 string 是该对象原本就是字符串类型, 而 str()则是将该对象转换成字符串类型。
kaisa_jiAmi(string,i)
def main():
print('请输入操作,注意不是平常26种:')
choice=input('1:恺撒加密,2:凯撒穷举解密.请输入1或2:')
if choice=='1':
string=input('请输入需要加密字符串:')
num=int(input('请输入需要加密的KEY:'))
kaisa_jiAmi(string,num)
elif choice=='2':
string=input('请输入需要解密字符串:')
kaisa_jiEmi(string)
else:
print('输入错误,请重试')
main()
if __name__=='__main__':
main()
哈哈哈低个头,看键盘嘛
用foremost提取一下图片,得到一个TXT文本
发现是AAEncode加密
https://www.cnblogs.com/rainforwind/articles/15358505.html
将js代码转换为颜文字的混淆工具(混淆:输出的一段颜文字可以直接执行并且得到与原js相同的结果)
或者控制台解密:去掉最后一行末尾的('_')
得到一张图片,用foremost提取分析发现有两张图片
010单看两张分离的图片没有什么特别之处,再查看原图,因为是两张JPG拼接,于是之前搜索FF D9
查看拼接处是否藏有信息
在拼接处发现可能是base32的字符串,解码即可
https://www.cnblogs.com/0yst3r-2046/p/11962942.html
(1)base16
使用16个ASCII可打印字符(数字0-9和字母A-F),对任意字节数据进行编码。
先获取输入字符串每个字节的二进制值(不足8比特在高位补0),然后将其串联进来,再按照4比特一组进行切分,将每组二进制数分别转换成十进制。
可以看到8比特数据按照4比特切分刚好是两组,所以Base16不可能用到填充符号“=”。
换句话说:Base16使用两个ASCII字符去编码原数据中的一个字节数据。
Base16编码是一个标准的十六进制字符串(注意是字符串而不是数值),更易被人类和计算机使用,因为它并不包含任何控制字符,以及Base64和Base32中的“=”符号。
(2)base32
Base32编码是使用32个可打印字符(字母A-Z和数字2-7)对任意字节数据进行编码的方案,编码后的字符串不用区分大小写并排除了容易混淆的字符,可以方便地由人类使用并由计算机处理。
Base32主要用于编码二进制数据,但是Base32也能够编码诸如ASCII之类的二进制文本。
Base32将任意字符串按照字节进行切分,并将每个字节对应的二进制值(不足8比特高位补0)串联起来,按照5比特一组进行切分,并将每组二进制值转换成十进制来对应32个可打印字符中的一个。
(3)base64
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。每6个比特为一个单元,对应某个可打印字符。3个字节有24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。
在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法。
它可用来作为电子邮件的传输编码。
Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据。
(4)base85
使用五个ASCII字符来表示四个字节的二进制数据,使用四个字符来表示三个字节的数据。
用途是Adobe的PostScript和Portable Document Format文件格式,以及Git使用的二进制文件的补丁编码。
与Base64一样,Base85编码的目标是对二进制数据可打印的ASCII字符进行编码。但是它使用了更大的字符集,因此效率更高一些。具体来说,它可以用5个字符编码4个字节(32位)。
(5)base36
Base36是一个二进制到文本编码表示方案的二进制数据以ASCII通过将其转化为一个字符串格式基数 -36表示。选择36十分方便,因为可以使用阿拉伯数字 0–9和拉丁字母 A–Z [1](ISO基本拉丁字母)表示数字。
每个base36位需要少于6位的信息来表示。(只支持整数)
(6)base58
Base58是用于Bitcoin中使用的一种独特的编码方式,主要用于产生Bitcoin的钱包地址。
相比Base64,Base58不使用数字"0",字母大写"O",字母大写"I",和字母小写"l",以及"+"和"/"符号。
设计Base58主要的目的是:
避免混淆。在某些字体下,数字0和字母大写O,以及字母大写I和字母小写l会非常相似。
不使用"+"和"/"的原因是非字母或数字的字符串作为帐号较难被接受。
没有标点符号,通常不会被从中间分行。
大部分的软件支持双击选择整个字符串。
(7)base91
base91需要91个字符来表示ASCII编码的二进制数据。从94个可打印ASCII字符(0x21-0x7E)中,以下三个字符被省略以构建base91字母:
-(破折号,0x2D)
\(反斜杠,0x5C)
'(撇号,0x27)
base91是将二进制数据编码为ASCII字符的高级方法。
它类似于UUencode或base64,但效率更高。base91产生的开销取决于输入数据。它的数量最多为23%(而base64为33%),范围可以降低到14%,通常发生在0字节块上。
这使得base91对于通过二进制不安全连接(例如电子邮件或终端线)传输较大的文件非常有用。
(8)base92
为了超越base82,尝试创造base92
在编码字符串时,`
和“
与普通引号'
太相似,以使其舒适。在区分l / 1
和0 / O
时使用的字体好。将〜
用作特殊符号(空字符串)。有94个可打印的ascii字符,因此最终得到91个字符,或每个字符6.5位。一旦包含〜
,则将有92个字符。
一旦每个字符有6.5位,则可以一次使用13位,并使用类似于base85的除法和取模方案,用它们产生两个输出字符。这可能意味着,与base92编码相比,它更能抵抗损坏,因为任何损坏都更加局限(一位更改仅影响2-3个字节,而不影响4个字节)。
注意:在某些需要某些输出的情况下,可能需要将〜
用作空字符串分号:
base64和base85更加优雅,将一个较小的字节整数干净地映射到另一个较小的字节整数。base92将13个字节映射为16个字符,从大小的角度来看,这比base85的4至5个字符更好,但是相当不雅观。
(9)base62
Base62编码将数字转换为ASCII字符串(0-9,az和AZ),反之亦然,这通常会导致字符串较短。
26个小写字母+26个大写字母+10个数字=62
62进制与10进制的互相转化
62进制转10进制与2进制转10进制相似。
2进制转10进制过程为:从右到左用二进制的每个数去乘以2的相应次方,次方要从0开始。
62进制转10进制也类似,从右往左每个数*62的N次方,N从0开始。
那么,10进制转62进制也与10进制转2进制类似。 即:不断除以62取余数,然后倒序。
关于短Url的转换
主要思路,维护一个全局自增的id,每来一个长url,将其与一个自增id绑定,然后利用base62将该自增id转换为base62字符串,即完成转换。
https://www.cnblogs.com/yunqian2017/p/15124198.html
题目为SQLtest,猜测可能和SQL注入有关,打开流量包先追踪一波HTTP流
盲注那就应该有很多注入语句,直接导出HTTP对象
导出后确实发现了很多盲注语句,但是阅读起来很困难
于是尝试用tshark提取
tshark -r sqltest.pcapng -Y"http.request" -T fields -e http.request.full_uri > data.txt
-r 读取文件
-Y 过滤语句
-T pdml|ps|text|fields|psml,设置解码结果输出的格式
-e 输出特定字段
http.request.uri http请求的uri部分
分析提取出的注入语句:
获取数据库库名
第九行获取information_schema.SCHEMATA中数据行数的长度(为1)
第18行获取information_schema.SCHEMATA中数据行数,chr(53) = '5'
,即infomation_schema.SCHEMATA有5行数据
(第19行-第61行+第65,66行)获取每一个数据库的长度
(62,63,64,第67-417行)获取每一个数据库库名
418行已经获取到了库名
表
第426行表名个数的长度(为1)
第435行表名个数
第444行表名长度
445-510行表名
第511行已经得到表名了
字段
第519行字段个数长度
第527行字段个数
第545行每个字段长度
546-601行获取每个字段字段名
值
第610行获取值个数的长度
第619行值的个数
第627行值的长度
628-972行获取我们需要的flag
这位大佬的python脚本
注入语句为:
id=1 and ascii(substr(((select concat_ws(char(94), flag) from db_flag.tb_flag limit 0,1)), {第i个字符}, 1))>{字符的ascii值}
把第i个字符和ascii值提取出来,取i变化时的值:
urllib.parse 模块提供了很多解析和组建 URL 的函数
urllib.parse.unquote:解码
strip:用于移除字符串头尾指定的字符(默认为空格)或字符序列
split:通过指定分隔符对字符串进行切片
find:方法检测字符串中是否包含子字符串 str,如果包含子字符串返回开始的索引值
import urllib.parse
f = open("data.txt","r").readlines()
s = []
for i in range(627,972):
# 处理文本
data = urllib.parse.unquote(f[i]).strip()
# 分割
payload = data.split("and")[1]
positions = payload.find("from db_flag.tb_flag limit 0,1)), ")
data1 = payload[positions+35:].split(",")[0]
data2 = payload[positions+35:].split(">")[1]
s.append([data1,data2])
for i in range(1,len(s)):
if s[i][0]!=s[i-1][0]:
print(chr(int(s[i-1][1])),end="")
print(chr(int(s[-1][1])))
或者提取出数据放入一个文本
with open('2.txt','r') as f:
data = f.readlines()
for i in data:
print(chr(int(i)),end="")
下载压缩包得到两个加密的压缩包,flag2没有密码提示也不是伪加密先不管,flag3提示六位纯数字密码,直接爆破得到一个Word文档和视频
打开文档发现有两串数字520和711可能和视频相关
RV打开视频也只有13s于是着重看一下5.20s和7.11s处,得到两处提示
第一处为敲击码
基于5×5方格波利比奥斯方阵来实现的,不同点是是用K字母被整合到C中,因此密文的特征为1-5的两位一组的数字,编码的范围是A-Z字母字符集,字母不区分大小写。
..... ../... ./... ./... ../
解码得到w l l m
第二处为base64解码即可:dXBfdXBfdXA=
结合可得字符串wllmup_up_up
尝试打开flag2得到一张图片,010查看,在文件尾得到flag
解压题目给出的压缩包得到很多txt文本
提示NTFS数据流,直接使用NtfsStreamsEditor
工具扫描flag
文件夹
https://www.qingsword.com/qing/812.html#windows-NTFS-ADS-2
NTFS磁盘格式的一个特性,在NTFS文件系统下,每个文件都可以存在多个数据流,就是说除了主文件流之外还可以有许多非主文件流寄宿在主文件流中。它使用资源派生来维持与文件相关的信息,虽然我们无法看到数据流文件,但是它却是真实存在于我们的系统中的。
创建一个数据交换流文件的方法很简单,命令为[宿主文件]:[准备与宿主文件关联的数据流文件]
NTFS分区,ADS是NTFS文件系统的特性,不适用于FAT32文件系统
lads.exe和streams.exe是用于检测交换数据流的程序
echo www.baidu.com>>123.txt:222.txt
使用echo命令,将"www.qingsword.com"这几个字符写入到123.txt:222.txt中;
echo命令以写字符的方式创建了"222.txt"这个交换数据流文件,其中123.txt是宿主文件,222.txt是交换数据流文件;
222.txt在图形界面下是不可见的,就像寄生虫一样,寄生在123.txt上。
notepad 123.txt:222.txt
使用记事本程序打开这个交换数据流文件,打开后可以添加删除222.txt的内容并保存,也能将数据流文件另存为保存成其他文件。
type 123.txt>>test:123.txt
将123.txt使用交换数据流的方式寄生到test文件夹上;
type命令和echo命令不同,type命令是将已经存在的一个文件,用交换数据流的方式寄生到另外一个文件或文件夹上;
test文件夹是一个空文件夹,寄生123.txt后,文件夹大小显示仍然是0。
notepad test:123.txt
使用notepad打开这个寄生在test上的文本文件
type 123.txt>>C:\:123.txt
将123.txt寄生到E盘根目录
notepad C:\:123.txt
这种方法能很好的将一个文本文件使用交换数据流的形式寄生在另外一个文件上(任何类型的文件上),从一定程度上起到了隐藏文本文件的目的。
type bbb.jpg>>123.txt:bbb.jpg
寄生到123.txt上
type bbb.jpg>>test:bbb.jpg
寄生到test文件夹上
type bbb.jpg>>aaa.exe:bbb.jpg
寄生到aaa.exe这个可执行文件上
type bbb.jpg>>C:\:bbb.jpg
寄生到C盘根目录
mspaint aaa.exe:bbb.jpg
打开方式很简单,可以使用系统自带的图画程序mspaint
#include<stdio.h>
int main(){
printf("hello world");
}
type aaa.exe>>123.txt:aaa.exe
寄生的方法和图片和文本文件相同,寄生到123.txt
type aaa.exe>>C:\:aaa.exe
寄生到C盘根目录
start 123.txt:aaa.exe
XP中可以直接用start命令执行可执行文件
mklink 111.txt 123.txt:aaa.exe
为 111.txt <<===>> 123.txt:aaa.exe 创建的符号链接
在命令行直接111.txt
即可运行此可执行文件
在Win7之后的系统中,微软可能出于安全考虑,不允许直接运行交换数据流可执行文件,必须要创建符号链接,这个符号链接是可见的(当然可以使用其他手段隐藏这个符号链接),并且这个符号链接创建出来后不能复制到其他地方,只能在创建的那个位置使用命令行方式调用(鼠标双击会报错)。
lads检测
lads.exe /S
(如果是在test文件下执行的话)递归检测test以及test下所有子目录。
streams清除
streams.exe -d C:\
首先尝试清除一下C盘根目录上面寄生的交换数据流,-d后面接目录。
这里报错因为这个:aaa.exe现在正在运行对于这种情况,需要先结束掉这个:aaa.exe进程才能清除。
streams.exe -s -d C:\
可以添加-s
参数来一次性递归清除C盘下所有寄生的交换数据流文件(慎用,尤其是对系统盘一定不要随便使用递归清除,系统本身的一些数据流也会被一起清除掉)
得到一个流量包,先尝试用foremost分离一下,得到一堆图片
发现第一张图片下面好像缺了什么
用ste查看图片在green通道1和0处即可得到flag
发现流量包里都是HTTP数据包,直接导出HTTP对象
在导出的文件中发现两张特别的图片
打开scanlines.png,在很多通道中都发现了一条线
logo.png图片中似乎缺了一块
将两张图片使用ste的Image Combiner对比,在相减时得到flag
打开题目给的流量包,数据包太多了,先导出HTTP对象看看
导出文件中发现一个secret.zip
加密压缩包
先尝试看看是不是伪加密
打开压缩包里的flag文件即可得到flag
拿到题目给的图片后尝试提取、查看十六进制都没有什么线索,于是再尝试用ste查看是否是LSB隐写
在RGB的0通道中发现不同,于是尝试用Data Extract提取
由上图可知明显是一张PNG但是文件头多了FF FE
,先保存文件用十六进制器处理,得到半张二维码
得到的图片明显高度有问题,直接十六进制器修改即可
得到一张二维码,虽然正常需要反色再扫,但是QR可以直接扫不用反色
访问给出的网址,得到一个压缩包
没有任何提示只有一个TXT那就尝试一下NTFS数据流,直接使用NtfsStreamsEditor
工具扫描flag
文件夹
果然得到一个pyc文件,直接反编译,或者使用uncompyle
库
uncompyle6 1.pyc > main.py
得到反汇编出的代码
# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: flag.py
# Compiled at: 2017-12-05 23:42:15
import base64
def encode():
# 加密函数
flag = '*************'
ciphertext = []
for i in range(len(flag)):
s = chr(i ^ ord(flag[i]))
# i与flag中第i个元素的ASCII的十进制异或
# 再把上述结果转换为ASCII
if i % 2 == 0:
s = ord(s) + 10
else:
s = ord(s) - 10
# 如果i能被二整除就叭ASCII转换为十进制再+10,否则-10
ciphertext.append(str(s))
# 得到的数加入列表
return ciphertext[::-1]
# 倒着输出
# 根据encode加密得到的列表
ciphertext = [
'96', '65', '93', '123', '91', '97', '22', '93', '70', '102', '94', '132', '46', '112', '64', '97', '88', '80', '82', '137', '90', '109', '99', '112']
# okay decompiling 1.pyc
解密脚本
# 密文
ciphertext = [
'96', '65', '93', '123', '91', '97', '22', '93', '70', '102', '94', '132', '46', '112', '64', '97', '88', '80',
'82', '137', '90', '109', '99', '112']
# 先把密文倒着排序
ciphertext = ciphertext[::-1]
flag = []
for i in range(len(ciphertext)):
# 如果i能被二整除就给十进制数 - 10,否则 + 10
if i % 2 == 0:
s = int(ciphertext[i]) - 10
else:
s = int(ciphertext[i]) + 10
# 异或然后再转换为ascii
flag.append(chr(int(i ^ s)))
# 打印flag
print("".join(flag))
题目提示需要逆向分析,首先用PEiD
看看是否加壳
未加壳,32位程序,用IDA进行分析,打开后用快捷键shift+F12(string window),发现了个很特别的字符串well done
(一般过关后会有类似字符串)
点击进入此字符串在内存中的位置
点击sub_401090,查看调用这个字符串的函数,跳转到汇编图形界面,按f5反编译查看伪C代码。
分析这个关键函数:
int __stdcall sub_401090(HWND hWnd, int a2, int a3, int a4)
hwnd是句柄,a2是消息,a3,a4是其他消息。
memset(String, 0, sizeof(String));
Value = 0;
memset:将string中当前位置后面的sizeof(String)个字节用0替换并返回string
GetDlgItemTextA(hWnd, 1002, String, 260); # 获取输入
strlen(String);
if ( strlen(String) > 6 ) # 输入字符串不能大于6
ExitProcess(0); # 退出程序
atoi(String)=122
所以sting的值为122xxx
,接下来把3,5,4转化成ascii码看看,
S3=x,S5=z,S4=y
v4 = atoi(String); # atoi函数:将字符串转换成整型
Value = v4 + 1;
v4 == 122 && String[3] == 120 && String[5] == 122 && String[4] == 121
flag赋值给text,然后是置零操作
strcpy(Text, "flag");
memset(&Text[5], 0, 0xFCu);
v8 = 0;
v9 = 0;
_itoa(Value, Source, 10);
itoa函数的功能是将int转化为char,第一个参数是要转化的值,第二个参数是转化后值的储存地址,第三个数是要转化的值的进制,这里为10进制。
strcat(Text, "{");
strcat(Text, Source);
strcat(Text, "_");
strcat(Text, "Buff3r_0v3rf|0w");
strcat(Text, "}");
第一条代码使Text="flag{"
,接着第二条指令使Text="flag{123"
,到最后Text="flag{123_Buff3r_0v3rf|0w}"
MessageBoxA(0, Text, "well done", 0);
messagebox,标题为well done,内容为Text
解压题目给的压缩包后全是加密的压缩包,但里面都只有一个TXT,并且很小只有四个字节
可以用CRC32爆破,大佬脚本跑一下
import zipfile
import string
import binascii
string=string.printable
crc_s=''
for i in range(0,68):
zip_name= "out" + str(i) + ".zip" #读每个文件
zip_crc=zipfile.ZipFile(zip_name,'r').getinfo('data.txt').CRC
#读crc
print(zip_crc)
for a in string:
for b in string:
for c in string:
for d in string:
s=a+b+c+d
#进行爆破
if zip_crc == (binascii.crc32(s.encode())):
print(s)
crc_s+=s
print(crc_s)
将爆破得到的所有压缩包里的txt中的内容按照文件顺序放在一起
z5BzAAANAAAAAAAAAKo+egCAIwBJAAAAVAAAAAKGNKv+a2MdSR0zAwABAAAAQ01UCRUUy91BT5UkSNPoj5hFEVFBRvefHSBCfG0ruGnKnygsMyj8SBaZHxsYHY84LEZ24cXtZ01y3k1K1YJ0vpK9HwqUzb6u9z8igEr3dCCQLQAdAAAAHQAAAAJi0efVT2MdSR0wCAAgAAAAZmxhZy50eHQAsDRpZmZpeCB0aGUgZmlsZSBhbmQgZ2V0IHRoZSBmbGFnxD17AEAHAA==
BASE64解密发现文件头虽然没有但是文件尾是RAR的,而且里面好像有文件
保存文件用十六进制器打开,添加文件头
RAR 文件头 52 61 72 21 1A 07 00
RAR 文件尾 C4 3D 7B 00 40 07 00
修改文件后缀,打开即可得到flag
得到一张图片大概查看了一下,先尝试用foremost提取,得到一个加密的压缩包,没有任何提示,先尝试四位数字爆破,得到一大串不知道干啥的码
看了大佬博客才知道对于一串大量无特征、无规律字符,可以用字频统计
# -*- coding:utf-8 -*-
#Author: mochu7
alphabet = "[email protected]#$%^&*()_+- =\\{\\}[]"
strings = open('./flag.txt').read()
result = {}
for i in alphabet:
counts = strings.count(i)
i = '{}'.format(i)
result[i] = counts
# 按照降序列出统计结果
res = sorted(result.items(),key=lambda item:item[1],reverse=True)
for data in res:
print(data)
# 按照词频输出
for i in res:
flag = str(i[0])
print(flag[0],end="") # 不换行
sorted(result.items(),key=lambda item:item[1],reverse=True)
sorted() 函数对所有可迭代的对象进行排序操作。
result.items():迭代对象,items()返回可遍历的(键, 值) 元组数组
key:比较元素,指定可迭代对象中的一个元素排序
key=lambda item:item[1]:按照频率排序
reverse=True:排序规则:降序
运行脚本即可得到flag
解压得到一个音频文件,那就先用Audacity康康
像是老年机按键声,用dtmf拨号识别一下wav文件
999*666*88*2*777*33*6*999*4*4444*777*555*333*777*444*33*66*3*7777
以上数字就是老年机的按键
999 ——> y
88 ——> u
777 ——> r
6 ——> m
4 ——> g
777 ——> r
333 ——> f
444 ——> i
66 ——> n
7777 ——> s
666 ——> o
2 ——> a
33 ——> e
999 ——> y
4444 ——> i
555 ——> l
777 ——> r
33 ——> e
3 ——> d