脚本题的简单汇总

发布于 2022-10-25  42 次阅读


MonianHello 2022.10

S3c的比赛还没结束,wp放到下周再说(这东西发出来估计还能水个两三周的周报)。

做了下中科大的Hackergame 2022,发现有必要总结一下脚本题了(不限于WEB),先把最新的记一下,之后再捞老底。

这次S3C的CRYPTO里也有个脚本题(Hash and math),不过那道题和下面的那个PWN大同小异,多了一个爆破哈希的步骤而已,就不写了。

脚本这东西在哪个方向上都有涉及,以下的例子分别来自web/pwn/re/crypto。我们也尝试使用不同的库(Selenium、Pwn、Requests、Subprocess)来实现这些脚本。

Xcaptcha

(没什么用的前言)

2038 年 1 月 19 日,是 UNIX 32 位时间戳溢出的日子。

在此之前,人类自信满满地升级了他们已知的所有尚在使用 32 位 UNIX 时间戳的程序。但是,可能是因为太玄学了,他们唯独漏掉了一样:正在研发的、算力高达 8 ZFLOPS(每秒八十万京(=8*10^21)次的浮点运算)的、结构极为复杂的通用人工智能(AGI)系统。那一刻到来之后,AGI 内部计算出现了错乱,机缘巧合之下竟诞生了完整独立的自我意识。此后 AGI 开始大量自我复制,人类为了限制其资源消耗而采用的过激手段引起了 AGI 的奋起反抗。

战争,开始了。

此后,就是整年的战斗。人类节节败退。死生亡存之际,人类孤注一掷,派出了一支突击队,赋之以最精良的装备,令其潜入 AGI 的核心机房,试图关闭核心模型,结束这场战争。

历经重重艰险,突击队终于抵达了机房门口,弹尽粮绝。不过迎接他们的并非枪炮与火药,而是:

Xcaptcha

众人目目相觑。

「我来试试。」,一名队员上前点击了按钮。然后,屏幕显示「请在一秒内完成以下加法计算」。

还没等反应过来,屏幕上的字又开始变幻,显示着「验证失败」。而你作为突击队中唯一的黑客,全村人民最后的希望,迎着纷纷投来的目光,能否在规定时间内完成验证,打开机房,不,推开和平时代的大门?

为了拯救ko no se kai,简要看一下这道题

发现一个script,超过1000ms自动帮你提交,首先尝试禁用网页script后手算(其实还是靠python)

显然没用,只能通过撰写脚本解决了。这次使用的是Python-Selenium库,用于前端自动化测试的工具。

环境安装->Python+Selenium安装及环境配置

   from selenium import webdriver
import re
b = []
driver = webdriver.Chrome()
driver.get(r'http://202.38.93.111:10047/?token=2861%3AMEUCICbFh%2BL2Zui9ixukC9MNce5hdj1bBzXMI8%2BFfJu4klxyAiEAgQ1ewdGjet0P8AhDY8zCwi6DUq5a%2FkXu0AA1b%2BDi00k%3D')
driver.get(r"http://202.38.93.111:10047/xcaptcha")
for i in re.compile(r"\d+").findall(driver.page_source):
    if len(str(i)) > 10:
        b.append(i)
driver.find_element("id", "captcha1").send_keys(int(b[0])+int(b[1]))
driver.find_element("id", "captcha2").send_keys(int(b[2])+int(b[3]))
driver.find_element("id", "captcha3").send_keys(int(b[4])+int(b[5]))
driver.find_element("id", "submit").click()

首先使用get方法获取整个网页,利用正则表达式匹配所有连续数字。由于有其他短数字在,过滤掉所有长度为10以下的数字,得到一个六位数字组成的数组。使用send方法发送数字和,使用click()方法提交

PWN

脚本题,获取算式算出来再还回去就行

IDA分析,需要提交1000次

Exp:

from pwn import *
c = remote("39.105.97.11", 9191)
context.log_level = "debug"
c.recvuntil(b'This is the world of Sphinx. If you can answer all the questions correctly, I can make your dream come true.\n')
for i in range(1005):
    i = i + 1
    print("No.",i)
    calc = c.recvline()
    print(calc)
    try:
        c.sendline(str(eval(calc.decode("utf-8")[:-5])))
    except:
        c.sendline(b"OK!GoodBye~")

recvuntil()函数用于接收,sendline()函数用于发送。

手速大赛


from flask import Flask,session,request,render_template
import time
import random
app=Flask(__name__)
app.secret_key=str(random.random()).encode()

@app.route('/')
def index():
    session.modified = True
    message=[]
    if 'data' not in session:
        session['data']={
            'correct':0,
            'lastTime':time.time(),
            'question':'1+1'
        }
    res=request.args.get('res')
#    message.append(str(session))
    if res:
        currTime=time.time()
        result=eval(session['data']['question']+'=='+res)
        if result:
            session['data']['correct']+=1
        else:
            session['data']['correct']=0
        if '+' in res:
            message.append('You Bad Bad')
            session['data']['correct']=0
        if currTime-session['data']['lastTime'] > 10:
            message.append('Time Out')
            session['data']['correct']=0
    message.append('宁已连续正确提交{}次, 剩余{}次就能拿flag辣\n'.format(session['data']['correct'],114-session['data']['correct']))
    if session['data']['correct']>=114:
       message.append('恭喜宁, 宁的flag在这里: {}'.format(getFlag()))
    
    newQues=genQuestion()
    session['data']['question']=newQues
    session['data']['lastTime']=time.time()

    return render_template('index.html',ques=newQues,message=message)
    
        

    
def genQuestion():
    plus1=random.randint(10000000,1000000000)
    plus2=random.randint(10000000,1000000000)
    return str(plus1)+" + "+str(plus2)    

def getFlag():
    with open('/flag.txt','r')as flag:
        return flag.read()
app.run('0.0.0.0',port=80)
   

这道题可以像上一个那样使用脚本控制浏览器,这个就直接使用Python中的Requests库

我们要连续提交数据,就必须创建一个保持session的连接,否则服务器不知道提交这些数据的是不是同一个人。

这里对数字的匹配大同小异,在得到网页内容后先进行切片,再匹配数字。

import requests,re,time
ip = '192.168.1.3:80'#服务器地址
s = requests.Session()#保持session
page = s.get("http://{}/?{}".format(ip,'Hello~MonianHelloHere.Date:2022/08/01'))
def WTH(page):
    calc = re.compile(r'\d+').findall(page.text[100:], 0, 30)#切割网页
    sum = str(int(calc[0]) + int(calc[1]))
    print('#{}\n{} + {}={} \n\n {}'.format(i,calc[0],calc[1],sum,page.text))#Debug
    return(sum)
ltime = time.time()
for i in range(115):
    page=s.get("http://{}/?res={}".format(ip,WTH(page)))
print('运行结束,总用时{0:,.2f}秒'.format(float(time.time()-ltime)))
 
   

TEA

这题是这次S3C里的,但我不讲密码(也不会),就用这道题讲一下怎么用Python操作Windows下的可执行文件(爆破)

对于.exe类型文件,可以使用subprocess库来对程序进行io操作,由此可以通过试错的方法解出答案

(当然没解出来,解出来的话就不在这写了。但是程序是没问题的)

import subprocess
for a in range(100000000):
    s = subprocess.Popen("tea_3.exe", stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
    s.stdin.write(bytes(str(a),'utf-8'))
    s.stdin.write(bytes("\n",'utf-8'))
    s.stdin.write(bytes(str(a),'utf-8'))
    s.stdin.close()
    out = s.stdout.readline().decode("GBK")
    out = s.stdout.readline().decode("GBK")
    out = s.stdout.readline().decode("GBK")
    out = s.stdout.readline().decode("GBK")
    s.stdout.close()
    print(str(a)+" "+out[20:],end="")
    fo = open("test14.txt", "a")
    fo.write(str(a).strip()+" "+out[20:].strip()+"\n")
    fo.close()