CTF-misc-进制转换
misc进制转换题
密文:bbaabbaabbabbaaabbaaaababbaabbbabbbbabbabaabaaaabbaabababbbbaaaababbbbbaabbaaababbbaabbababbbbbaabbaaababbabbababbbaaaaaabbaaaaabbbaabaabbbabaaabaaaaaaabbabbbaabbbabaaabbbbbab
准备工作
说了是进制转换:为了补知识点去找了一篇博客看看进制转换考啥:https://blog.csdn.net/robacco/article/details/104697705/
总结:核心就是,以某种形式,转成十进制后,找与ASCII码的对应关系(比如可以比对和f
,{
的编码关系)。
ASCII码
一共128个,二进制占七位,八进制占三位少一个二进制位,十六进制占两位少一个二进制位
常用字符
ASCII | Char |
---|---|
102 | f |
123 | { |
全码表:https://www.sojson.com/ascii.html
python对字符数字和数字的转换
python和c/c++对于字符转换的不同在于,python中默认字符数字转换后是这样的(更符合直觉嗯哼)
# int()是转换为int类型str()同理
print(int('115')==115) # True
print(str(115)=='115') # True
与之对比C/C++的转换是这样的(为了保证兼容性用C的写法,C++同理)
#include <stdio.h>
int main(){
char a[4] = "115";
register int i;
for(i=0; i<3; i++){
printf("%d ",(int)a[i]);
}
return 0;
}
//输出结果 49 49 53,也就是1 1 5这三个字符在ASCII编码表中的对应编码
//1的编码值是49
//5的编码值是53
那python的转换确实更符合直觉(实际上像JavaScript这种新出的语言基本上都是这样的,因为更符合逻辑),但是如果想转编码怎么办呢?于是python定义了这几个函数用于转换编码
ord('单个字符(类型为str)')
- 返回值是对应的十进制表示的ASCII码
print(ord('1'))
输出49
chr(单个字符对应的ASCII码(类型为整型))
- 返回值是对应的字符
print(chr(49))
输出1
python中的进制转换
先来说说最常用的怎么从任意进制转为十进制
str = '1110011' # 二进制
# int(argument1, argument2)
# 第一个参数为原始值,注意这里传入的得是字符串类型
# 第二个参数为原始进制,也就是str的进制
print(int(str, 2)) # 115
接下来讲讲十进制转为其他进制,首先要看看这个 点击查看 进制表示 的相关字符
那么就很好记python中其余的进制转换函数了,注意,函数名代表目标进制,用法略有点不同,他们只支持十进制转成对应进制,怎么转十进制呢?就是用到上述的int()
了
str = 115
print(bin(str))
print(oct(str))
print(hex(str))
'''
>>> str = 115
>>> print(bin(str))
0b1110011
>>> print(oct(str))
0o163
>>> print(hex(str))
0x73
'''
# 注意返回值是字符串
print(type(hex(str))) # <class 'str'>
python的进制转换相关函数:
其他进制转二进制----bin(var)
其他进制转八进制----oct(var)
其他进制转十进制----int(var),其实不管赋值时用什么进制默认输出都是十进制,所以可以不需要转换
其他进制转十六进制----hex(var)其他进制转十进制Int(str,n)#n为进制
ASCII码:
一共128个,二进制占七位,八进制占三位少一个二进制位,十六进制占两位少一个二进制位
结合本题,那应该是每七位转成一个ASCII字符,结合测试len(str_bin)
的输出结果是175正好能被7整除!
用python代码尝试,划分七位,但是对照着flag的开头这样无论咋样也得不到flag,最类似的情况是在a==0 b==1的位置第一个字符是f但是其他都乱码,撞墙了。
感谢的前面chs大佬的提示,我换用 八位 和 a0 b1试一下,解出来了,贴一个代码
试错
根据ASCII码的知识,结合本题,尝试着将ab转为二进制
- a=0 b=1
1100110011011000110000101100111011110110100100001100101011110000101111100110001011100110101111100110001011011010111000000110000011100100111010001000000011011100111010001111101
- a=1 b=0
0011001100100111001111010011000100001001011011110011010100001111010000011001110100011001010000011001110100100101000111111001111100011011000101110111111100100011000101110000010
- 长度为 175
试了一下能被7整除,于是尝试划分七位,各自高低位补0转成ASCII码,一共四个情况,但是无论如何也推不出答案。最类似的情况是在a==0 b==1的位置第一个字符是f但是其他都乱码,撞墙了。
正解
感谢的chs大佬的提示,原来是用八位切割的,我换用 八位 和 a0 b1试一下,但是少一位啊?我就把末尾补了一个0正常切割,然后对比
开头的那个字符ASCII编码(经测试是204
)和这两个字符的关系,惊奇的发现除以二就是f的编码了,于是对全部的字符编码都除以二处理
ASCII | Char |
---|---|
102 | f |
123 | { |
于是就解出答案了,代码如下,结合前面知识点的很好理解
str = 'bbaabbaabbabbaaabbaaaababbaabbbabbbbabbabaabaaaabbaabababbbbaaaababbbbbaabbaaababbbaabbababbbbbaabbaaababbabbababbbaaaaaabbaaaaabbbaabaabbbabaaabaaaaaaabbabbbaabbbabaaabbbbbab'
str_bin = ''
for i in str:
if i == 'a':
str_bin = str_bin + '0'
else:
str_bin = str_bin + '1'
print("")
str_bin = str_bin + '0'
print(len(str_bin))#175/7=25.0 175/8=21...7
ans = ""
for i in range(22):
tmp = int(str_bin[i*8:i*8+8],2)#单个字符2转10进制
tmp = int(tmp/2)
ans = ans + chr(tmp)
# print('0'+str_bin[i*7:i*7+7],tmp,chr(tmp),'|',end="")
print("")
print(ans)
进制转换题总结
- 巧合可能是陷阱
核心思路就是:以某种形式,转成十进制后,找与ASCII码的对应关系
- 因为实际储存中ASCII码占一byte也就是八位,故二进制转十进制一般也是八个一转,虽然实际只有六位
- 比如可以比对和
f
,{
的编码关系 - 因为答案一般都是flag{}或者{}所以开头很可能就是
f
或{