2 What-is-this
AZADI TOWER
3 Avatar
题目
一个恐怖份子上传了这张照片到社交网络。里面藏了什么信息?隐藏内容即flag
解题
┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/outguess]
└─$ outguess -r 035bfaa85410429495786d8ea6ecd296.jpg flag1.txt
Reading 035bfaa85410429495786d8ea6ecd296.jpg....
Extracting usable bits: 28734 bits
Steg retrieve: seed: 94, len: 41
┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/outguess]
└─$ cat flag1.txt
We should blow up the bridge at midnight
┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/outguess]
└─$
flag
We should blow up the bridge at midnight
4 base64stego
压缩包是否为伪加密的判断
1、无加密:
(1)压缩源文件数据区的全局加密标志应当为00 00
(2)且压缩源文件目录区的全局方式位标记应当为00 00
2、伪加密:
(1)压缩源文件数据区的全局加密标志应当为00 00
(2)且压缩源文件目录区的全局方式位标记应当为09 00
3、真加密
(1)压缩源文件数据区的全局加密标志应当为09 00
(2)且压缩源文件目录区的全局方式位标记应当为09 00
50 4B 03 04:文件头标记(0x04034B50)
14 03:解压文件所需 pkware 版本
00 00:全局方式位标记(判断真伪加密的重要标志)
08 00:压缩方式
68 BF:最后修改文件时间
9B 48:最后修改文件日期
FE 32 7D 4B:CRC-32校验
E9 0D 00 00:压缩后尺寸
B5 1B 00 00:未压缩尺寸
09 00:文件名长度
00 00:扩展记录长度
50 4B 01 02:目录中文件文件头标记(0x02014B50)
3F 03:压缩使用的 pkware 版本
14 03:解压文件所需 pkware 版本
09 00:全局方式位标记(数据区的加密标志为00 00,所以判断这是伪加密,将09 00 改为00 00即可)
08 00:压缩方式
68 BF:最后修改文件时间
9B 48:最后修改文件日期
FE 32 7D 4B:CRC-32校验(1480B516)
E9 0D 00 00:压缩后尺寸(25)
B5 1B 00 00:未压缩尺寸(23)
09 00:文件名长度
24 00:扩展字段长度
00 00:文件注释长度
00 00:磁盘开始号
00 00:内部文件属性
20 80 ED 81:外部文件属性
00 00 00 00:局部头部偏移量
将该压缩包的压缩源文件的全局方式位标记由09 00 改为00 00即可解压该文件,
通过解压文件我们可以得到一个文本文档。打开后可以看到是一些base64字符,我们写个脚本跑一下
python
import base64
bin_str=''
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
with open('stego.txt','r') as f: # 这里要改成你的文件路径
for line in f.readlines():
s64="".join(line.split())
r64="".join(str(base64.b64encode(base64.b64decode(s64)),'utf-8').split())
offset=abs(b64chars.index(s64.replace('=','')[-1])-b64chars.index(r64.replace('=', '')[-1]))
equal=line.count('=')
if equal:
bin_str += bin(offset)[2:].zfill(equal * 2)
print(''.join([chr(int(bin_str[i:i + 8], 2)) for i in range(0,len(bin_str),8)]))
Base_sixty_four_point_five
5 Guess-the-Number
下载附件后是一个jar文件,解压一下得到一个class文件,用 jd-gui反汇编得到guess.class文件源码。
java
import java.math.BigInteger;
public class guess
{
static String XOR(String _str_one, String _str_two) {
BigInteger i1 = new BigInteger(_str_one, 16);
BigInteger i2 = new BigInteger(_str_two, 16);
BigInteger res = i1.xor(i2);
String result = res.toString(16);
return result;
}
public static void main(String[] args) {
int guess_number = 0;
int my_num = 349763335;
int my_number = 1545686892;
int flag = 345736730;
if (args.length > 0) {
try {
guess_number = Integer.parseInt(args[0]);
if (my_number / 5 == guess_number) {
String str_one = "4b64ca12ace755516c178f72d05d7061";
String str_two = "ecd44646cfe5994ebeb35bf922e25dba";
my_num += flag;
String answer = XOR(str_one, str_two);
System.out.println("your flag is: " + answer);
} else {
System.err.println("wrong guess!");
System.exit(1);
}
} catch (NumberFormatException e) {
System.err.println("please enter an integer \nexample: java -jar guess 12");
System.exit(1);
}
} else {
System.err.println("wrong guess!");
int num = 1000000;
num++;
System.exit(1);
}
}
}
阅读代码,将用户输入的数字存入guess_number,当my_number / 5 == guess_number时才会进行计算flag的程序,my_number / 5 = 309137378,将guess_number的值修改为309137378,执行代码成功获得flag。
bash
┌──(holyeyes㉿kali2023)-[~/Misc/timu/zulu/Guess-the-Number]
└─$ java -jar 6a8bee79ee404194bb8a213a8a0e211d.jar 309137378
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
your flag is: a7b08c546302cc1fd2a4d48bf2bf2ddb
python
str_one ='4b64ca12ace755516c178f72d05d7061'
str_two ="ecd44646cfe5994ebeb35bf922e25dba"
"""
1、int(x,base) 若 x 为纯数字,则不能有 base 参数,否则报错;其作用为对入参 x 取整
2、若 x 为 str,则 base 可略可有。
base 存在时,视 x 为 base 类型数字,并将其转换为 10 进制数字。若 x 不符合 base 规则,则报错
"""
a=int(str_one,16)
b=int(str_two,16)
print('a=',a)
print(hex(a ^ b)) #hex() 函数用于将10进制整数转换成16进制,以字符串形式表示
def x_o_r(byte1, byte2): # 传入两个数,并返回它们的异或结果,结果为16进制数
return hex(byte1 ^ byte2)
print(x_o_r(a, b)[2:]) #[2:]表示从字符串012,2的下标开始取值
6 enc
file:///E:/逐鹿/MISC/tools/koczkatamas.github.io-master/tools.html
file:///E:/逐鹿/MISC/tools/CyberChef_v10.18.9/CyberChef_v10.18.9.html
到这里就只能猜格式了,首先转换为小写:
th15o1so5up3ro5ecr3totxt
加上花括号,将o替换为_ 即可得:
ALEXCTF{th15_1s_5up3r_5ecr3t_txt}
7 easy_RSA
python
import gmpy2
p=473398607161
q=4511491
e=17
d = gmpy2.invert(e,(q-1)*(p-1))
print(d)
125631357777427553
8 二元一次方程组
python
import libnum
from Crypto.Util import number
from secret import flag
size = 256
e = 65537
p = number.getPrime(size)
q = number.getPrime(size)
avg = (p+q)/2
n = p*q
m = libnum.s2n(flag)
c = pow(m, e, n)
print('n = %d' % n)
print('avg = %d' % avg)
print('c = %d' % c)
'''
n = 5700102857084805454304483466349768960970728516788155745115335016563400814300152521175777999545445613444815936222559357974566843756936687078467221979584601
avg = 75635892913589759545076958131039534718834447688923830032758709253942408722875
c = 888629627089650993173073530112503758717074884215641346688043288414489462472394318700014742820213053802180975816089493243275025049174955385229062207064503
'''
https://blog.csdn.net/figfig55/article/details/128635495
python
import libnum
# extended euclidean algorithm
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
# modular multiplicative inverse
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
n = 5700102857084805454304483466349768960970728516788155745115335016563400814300152521175777999545445613444815936222559357974566843756936687078467221979584601
avg = 75635892913589759545076958131039534718834447688923830032758709253942408722875
c = 888629627089650993173073530112503758717074884215641346688043288414489462472394318700014742820213053802180975816089493243275025049174955385229062207064503
e = 65537
phi_n = n - 2*avg + 1 # phi(n) = (p-1)(q-1) = pq-(p+q)+1
d = modinv(e, phi_n) # de = 1 mod phi_n, d = e^-1 mod phi_n
m = pow(c, d, n)
print(libnum.n2s(m))
9 Xor很心疼你
python
# Python3
from secret import flag
import random
import base64
pool = 'qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM'
r = random.randint(2, 250)
assert flag.startswith('hsctf{')
def generate(length):
return ''.join(random.choices(pool, k=length))
def f(x):
random.seed(x)
return random.getrandbits(8)
def encrypt(plaintext, key):
plaintext = list(map(ord, plaintext))
for _ in range(20):
key = f(key)
assert key != 0
for i in range(len(plaintext)):
key = f(key)
tmp = (key * r) % 251
assert tmp != 0 and key != 0
plaintext[i] = plaintext[i] ^ tmp
plaintext = bytes(plaintext)
return base64.b64encode(plaintext)
m = generate(random.randint(200, 300)) + flag + generate(random.randint(200, 300))
c = encrypt(m, random.getrandbits(128))
print(c)
# b'8OcTbAfL6/kOMQnC9v8SNmmSzvQMeGTT8vANM1T+7vIce2fo0fc2RnScrNxTSmeSyuMjMF//w8BWaXX91dsGcnvmreg0NQTw96ceVVXj3sQ3Znn51OU1S0bOyaMtNHTj36AcWFqewN4zRUXD6agGbAPE+tQtd3XG0doAa1Ll9fhcQ1zk0McTM1bv8PIQOAnn3vQ3UgLD3PsONXLs4KkXMnjTyMEQOFn/0uYVUwOY1PsleEHCyNopRVDr+Kc0e2PH9v0XNXfprfIPU3nw7KYTNX/G7twLSkHoyaUlQHXi3v02UHmdy/4iNgme3Pc8bgPp+tYWV1+YzPkXYkXM4ulUc27DrM4SNUPT2fQlckj1qP4Fal+YoPYJMlyZ8qhXfF3Y0tUDdUXl3vg0dFTi++VVOFfH/dgMS1ru9N8WU0HF9cUCTgPe+qVdSn/u7Mkda0GTw/QDcWPZ9KYGN2jSzfk0OVrMzt0yRHD64KMrUgPF2sFWcmP56KZSTAD61PUGeXrd49MgU1bL8OsVNWj91vIsalXwqf0qaWbwzv0lWETA4eElS3L99cYmU1nv9dRQTWbDyclScQTN6NIhV2j//+ZWbH7Z68kwM3Dy4dcUc1PQy8kRTl/4zcU9WGWfoakOMXuf69MXZQTEz+kJT1Dar8UN'
大概分析一下题目逻辑,首先明文 m 是 flag 前后各加200多个字符padding生成的字符串。
加密得到密文的函数 encrypt 逻辑包括:
首先把明文转为数组,数组元素即明文字符的ASCII值
然后调用20次 key = f(key) 取随机字节,上一次的返回值作为下一次的随机数种子
然后遍历每个明文字符,每次调用 key = f(key) 取一个随机字节,然后计算 tmp = (key * r) % 251 其中 2<r<250,最后将当前明文字符与 tmp 进行一次异或加密
随机数题目还是要先解决种子未知的问题,好在这个题目 key,r 都只有8位,直接爆破,寻找 hsctf{ 正确加密后的密文,然后就是个简单的异或解密了。
python
# Python3
#from secret import flag
import random
import base64
cc=b'8OcTbAfL6/kOMQnC9v8SNmmSzvQMeGTT8vANM1T+7vIce2fo0fc2RnScrNxTSmeSyuMjMF//w8BWaXX91dsGcnvmreg0NQTw96ceVVXj3sQ3Znn51OU1S0bOyaMtNHTj36AcWFqewN4zRUXD6agGbAPE+tQtd3XG0doAa1Ll9fhcQ1zk0McTM1bv8PIQOAnn3vQ3UgLD3PsONXLs4KkXMnjTyMEQOFn/0uYVUwOY1PsleEHCyNopRVDr+Kc0e2PH9v0XNXfprfIPU3nw7KYTNX/G7twLSkHoyaUlQHXi3v02UHmdy/4iNgme3Pc8bgPp+tYWV1+YzPkXYkXM4ulUc27DrM4SNUPT2fQlckj1qP4Fal+YoPYJMlyZ8qhXfF3Y0tUDdUXl3vg0dFTi++VVOFfH/dgMS1ru9N8WU0HF9cUCTgPe+qVdSn/u7Mkda0GTw/QDcWPZ9KYGN2jSzfk0OVrMzt0yRHD64KMrUgPF2sFWcmP56KZSTAD61PUGeXrd49MgU1bL8OsVNWj91vIsalXwqf0qaWbwzv0lWETA4eElS3L99cYmU1nv9dRQTWbDyclScQTN6NIhV2j//+ZWbH7Z68kwM3Dy4dcUc1PQy8kRTl/4zcU9WGWfoakOMXuf69MXZQTEz+kJT1Dar8UN'
cc=base64.b64decode(cc)
flag = 'hsctf{'
pool = 'qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM'
#r = random.randint(2, 250)
assert flag.startswith('hsctf{')
def generate(length):
return ''.join(random.choices(pool, k=length))
def f(x):
random.seed(x)
return random.getrandbits(8)
def encrypt(plaintext, key):
plaintext = list(map(ord, plaintext))
for i in range(len(plaintext)):
key = f(key)
tmp = (key * r) % 251
#assert tmp != 0 and key != 0
plaintext[i] = plaintext[i] ^ tmp
plaintext = bytes(plaintext)
return plaintext
def decrypt(ciphertext, key):
ciphertext=list(ciphertext)
for i in range(len(ciphertext)):
key = f(key)
tmp = (key * r) % 251
#assert tmp != 0 and key != 0
ciphertext[i] = ciphertext[i] ^ tmp
ciphertext = bytes(ciphertext)
return ciphertext
for r in range(2,251):
for key in range(1,256):
m = flag
c = encrypt(m, key)
if(c in cc):
print(r)
print(key)
print(c)
print(cc.index(c))
r=187
key=34
pos=247
mm=decrypt(cc[247:],key)
print(mm)
hsctf{Dl3F4TH3rRR4iin_AvAvA}