强网杯2020-dice2crybaby_crtbank
Web2 dice2cry
操作內(nèi)容:
輸入token后抓包
發(fā)現(xiàn)這邊給我們設(shè)置了一些cookie
一看就知道這是一個RSA加密的密文,公鑰n以及公鑰e的值
然后抓包roll骰子那個界面
發(fā)現(xiàn)他會隨機(jī)返回給我們一個數(shù)字,大概是0-2樣子
這邊發(fā)現(xiàn)abi.php有一個備份文件abi.php.bak
拿到這個abi.php的一個后臺源碼
<?php session_start(); header("Content-type:text/html;charset=utf-8"); $data = json_decode($json_string, true); $rand_number = isset($_POST['this_is.able']) ? $_POST['this_is.able'] : mt_ rand(); $n = gmp_init($data['n']); $d = gmp_init($data['d']); $c = gmp_init($rand_number); $m = gmp_powm($c,$d,$n); $v3 = gmp_init('3'); $r = gmp_mod($m,$v3); $result=(int)gmp_strval($r); $dice = array("num"=>$result); $json_obj = json_encode($dice); echo $json_obj; ?>通過分析大概邏輯就是
我們可以輸入一個this_is.able,如果接受到,就把他作為RSA里面的密文c的值。
如果不存在這個傳參的輸入那么就隨機(jī)定義為一個隨機(jī)數(shù)。
然后這個密文c的值會被解密出明文m,然后返回給我們的result為明文m%3的結(jié)果。
這邊在密碼學(xué)里面很常見,就是一個RSA Parity Oracle Attack的一個變形。像RSA Parity Oracle Attack的話是利用返回結(jié)果進(jìn)行一個二分法去逼近正確的m。這題的話是mod3的,所以我們改成三分法去求解就好了。
但是這邊發(fā)現(xiàn),我們傳入this_is.able后,返回的結(jié)果還是變化的。本地調(diào)試了一下,發(fā)現(xiàn)參數(shù)為this_is.able無法傳入值。發(fā)現(xiàn)this_is.able的.符號會被轉(zhuǎn)義成下劃線_
這邊的話其實之前有個題是考察php特性的,就是知道有些符號會被轉(zhuǎn)義成下劃線。
這邊的話就去找php的一個底層特性的實現(xiàn),發(fā)現(xiàn)空格和點被轉(zhuǎn)義為了下劃線
通過審計發(fā)現(xiàn),當(dāng)輸入[號時,[號會被轉(zhuǎn)義為下劃線,但是后面的內(nèi)容不會被匹配。于是我們這邊利用了this[is.able進(jìn)行繞過。然后去跑一個RSA的三分法攻擊腳本就好了。
首先是我本地打RSA系統(tǒng)的一個腳本
模擬服務(wù)端,調(diào)試了一下改哪個奇偶攻擊的腳本。改成一個三分法的逼近明文m的腳本。
from Crypto.Util.number import * import gmpy2flag = 'flag{hahahhahahahhahahhahahhaha}'n=105956881680544559949917851567380684862138560300472703220457685666736236228802991190021885463348407165737558806991007895462808203457554499754532933347069118199504385800332444768661297496997465739842040185258271659284920709002422077100572993201839354073420950313901600613811047294937751742958700306169399252501 e=0x10001 d=99132583992618982222090772948189787036435722773147752729993491529084319706506007412719256741545553409133224831918773213882197045992392262492163836323128748455149096839927635949026840001467301723519783221985012361184009811664174207173356526802063414660284820403017146461784740437030490639199947243220673575345 c=60621414499700748395208135299921126015752771639304798642532782445552120416470468032634076167976435587315602555150113020338637160818751595739320295141064187015713274649441493292261499375392734520779134951500287206836286388102757292207908048517923113200578884768924776328862960096669012548625047827952932916182 def decode(c):return pow(c,d,n)%3def brute_flag(encrypted_flag, n, e):flag_count = n_count = 1flag_lower_bound = 0flag_upper_bound = nciphertext = encrypted_flagmult = 1while flag_upper_bound > flag_lower_bound +1:ciphertext = (ciphertext * pow(3, e, n)) % nflag_count *= 3n_count = n_count * 3 - 2print("bit = %d" % mult)mult += 1data=decode(ciphertext)print(data)if(data==0):flag_upper_bound = n * n_count // flag_countelif(data==1):flag_lower_bound = n * n_count // flag_countn_count += 2else:flag_lower_bound = n * n_count // flag_countn_count += 1return flag_lower_bound re=brute_flag(c,n,e) from Crypto.Util.number import * print(long_to_bytes(re))這邊成功在本地打出flag的一個明文m
然后去改一個和web服務(wù)交互的腳本
最終打服務(wù)端flag的腳本如下:
import requestsdef getMmod3(c):url = "http://106.14.66.189/abi.php"payload = {"this[is.able":str(c)}headers = {"Cookie":"PHPSESSID=3d5q3d0bkl04nul507qd2oglfd; encrypto_flag=13481861255372436588960946085494101299803016402060111214242134714961484800546887418026900751080223654351911083589256183853303318498078822754604444578718557858387407654039131549529110684586550438802482061736216467019770380792142960641682901877073673961938563714234216270289002702435231964142578365021218806946; public_n=8f5dc00ef09795a3efbac91d768f0bff31b47190a0792da3b0d7969b1672a6a6ea572c2791fa6d0da489f5a7d743233759e8039086bc3d1b28609f05960bd342d52bffb4ec22b533e1a75713f4952e9075a08286429f31e02dbc4a39e3332d2861fc7bb7acee95251df77c92bd293dac744eca3e6690a7d8aaf855e0807a1157; public_e=010001"}response = requests.request("POST", url, data=payload, headers=headers)print(response.text)return response.textdef brute_flag(encrypted_flag, n, e):flag_count = n_count = 1flag_lower_bound = 0flag_upper_bound = nciphertext = encrypted_flagmult = 1while flag_upper_bound > flag_lower_bound + 1:ciphertext = (ciphertext * pow(3, e, n)) % nflag_count *= 3n_count = n_count * 3 - 2print("bit = %d" % mult)mult += 1data=getMmod3(ciphertext)print(data=="{\"num\":0}")if(data=="{\"num\":0}"):flag_upper_bound = n * n_count // flag_countelif(data=="{\"num\":1}"):flag_lower_bound = n * n_count // flag_countn_count += 1else:flag_lower_bound = n * n_count // flag_countn_count += 2return flag_lower_boundc=13481861255372436588960946085494101299803016402060111214242134714961484800546887418026900751080223654351911083589256183853303318498078822754604444578718557858387407654039131549529110684586550438802482061736216467019770380792142960641682901877073673961938563714234216270289002702435231964142578365021218806946 n=0x8f5dc00ef09795a3efbac91d768f0bff31b47190a0792da3b0d7969b1672a6a6ea572c2791fa6d0da489f5a7d743233759e8039086bc3d1b28609f05960bd342d52bffb4ec22b533e1a75713f4952e9075a08286429f31e02dbc4a39e3332d2861fc7bb7acee95251df77c92bd293dac744eca3e6690a7d8aaf855e0807a1157 e=0x10001 re=brute_flag(c,n,e) from Crypto.Util.number import * print(long_to_bytes(re))強(qiáng)網(wǎng)先鋒2 baby_crt
操作內(nèi)容:
這邊拿到了相關(guān)的paper
這邊我們得到的數(shù)據(jù)有n、m、sig、e。c1未知,但是我們可以知道c1最后是mod上t1的,t1是小于e的,e是65537,所以我們對他進(jìn)行爆破即可。
n=26318358382258215770827770763384603359524444566146134039272065206657135513496897321983920652242182112479484135343436206815722605756557098241887233837248519031879444740922789351356138322947108346833956405647578838873425658405513192437479359531790697924285889505666769580176431360506227506064132034621123828090480606055877425480739950809109048177976884825589023444901953529913585288143291544181183810227553891973915960951526154469344587083295640034876874318610991153058462811369615555470571469517472865469502025030548451296909857667669963720366290084062470583318590585472209798523021029182199921435625983186101089395997 m=26275493320706026144196966398886196833815170413807705805287763413013100962831703774640332765503838087434904835657988276064660304427802961609185997964665440867416900711128517859267504657627160598700248689738045243142111489179673375819308779535247214660694211698799461044354352200950309392321861021920968200334344131893259850468214901266208090469265809729514249143938043521579678234754670097056281556861805568096657415974805578299196440362791907408888958917063668867208257370099324084840742435785960681801625180611324948953657666742195051492610613830629731633827861546693629268844700581558851830936504144170791124745540 sig=20152941369122888414130075002845764046912727471716839854671280255845798928738103824595339885345405419943354215456598381228519131902698373225795339649300359363119754605698321052334731477127433796964107633109608706030111197156701607379086766944096066649323367976786383015106681896479446835419143225832320978530554399851074180762308322092339721839566642144908864530466017614731679525392259796511789624080228587080621454084957169193343724515867468178242402356741884890739873250658960438450287159439457730127074563991513030091456771906853781028159857466498315359846665211412644316716082898396009119848634426989676119219246 e = 65537 import gmpy2 from hashlib import sha1 from Crypto.Util.number import getPrime, long_to_bytes, getStrongPrime for c1 in range(65537):if gmpy2.gcd(pow(m,c1,n)-pow(sig,e,n),n)!=1:p=gmpy2.gcd(pow(m,c1,n)-pow(sig,e,n),n) q=n//p assert(p*q==n) if p>q:p=q flag = "flag{" + sha1(long_to_bytes(p)).hexdigest() + "}" print(flag)強(qiáng)網(wǎng)先鋒5 bank
操作內(nèi)容:
nc 連接題目靶機(jī)
發(fā)現(xiàn)首先是一個pow。爆破前三個內(nèi)容
就直接拿pow腳本爆破一下,然后發(fā)送token進(jìn)入題目。
有幾個選項。
hint里面給了我們一個AES加密的函數(shù),大概意思就是會把我們交易的記錄給加密,然后是分塊加密的,分別加密發(fā)送者,接收者和金額。
get flag發(fā)現(xiàn)需要支付1000,但是我們只有10
provide a record 主要是提示我們可以提交記錄,也會去執(zhí)行這條記錄去轉(zhuǎn)賬。
transact 轉(zhuǎn)賬,生成一個轉(zhuǎn)賬的記錄
view records 系統(tǒng)應(yīng)該是每次訪問會自動先生成很多的一個記錄。
這邊的攻擊思路就是,去transact里面先轉(zhuǎn)個帳,目的是拿到我們的一個AES加密后的32位的一個東西。
然后去records里面把記錄里面中間32位,也就是接收者改成我們的。
然后提交到provide a record里面
寫腳本自動完成操作
發(fā)現(xiàn)有了1500
去get flag
import os import re from itertools import product from hashlib import sha256 from pwn import *add = "39.101.134.52" port = 8005def login(io):rec = io.recvline().decode()s = string.ascii_letters + string.digitssuffix = re.findall(r'\(XXX\+(.*?)\)', rec)[0]digest = re.findall(r'== (.*?)\n', rec)[0]for i in product(s, repeat=3):prefix = ''.join(i)guess = prefix + suffixif sha256(guess.encode()).hexdigest() == digest:# print(guess)breakprint(prefix)io.sendafter(b'Give me XXX:', prefix.encode())returnsh = remote(add,port)login(sh)sh.sendafter(b'teamtoken:', "icqf0c3ad90f1390788c95c282e39ca4".encode()) sh.sendafter(b'give me your name:', "1".encode()) sh.sendafter(b'>', "transact".encode()) sh.sendafter(b'>', "2 1".encode()) my_sig=sh.recvuntil("your")[1:33] sh.sendafter(b'>', "view records".encode()) sh.recvline()re=[] for i in range(10):record=sh.recvline().strip("\n")re.append(record[0:32]+my_sig+record[-32:])for i in range(10):sh.sendafter(b'>', "provide a record".encode())sh.sendafter(b'>', re[i].encode())sh.interactive()總結(jié)
以上是生活随笔為你收集整理的强网杯2020-dice2crybaby_crtbank的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android异步线程利用Handler
- 下一篇: 关于Crypto.PublicKey.R