# SECCON writeup ## crypto ### r_and_b 問題ファイルを開くと、FLAGを暗号化するpythonスクリプトとエンコードされたFLAGがあります。 暗号化処理(?)は、FORMATの文字列によってrot13かbase64のどちらかをFLAGに対して繰り返し処理をします。 ですが、暗号化処理は、rot13かbase64にて処理した文字列とFORMATの一文字を追加しているので、追加された一文字目によって復号化処理をすればいいです。 ```python import base64 import codecs fin = open("encoded_flag","r") data= fin.read() for i in range(10): if data[0] =="B": data = base64.b64decode(data[1:]) print(data) if data[0] == "R": data= codecs.decode(data[1:],"rot13") print(data) fin.close() ``` ## reversing ### mask 解析: > $objdump; $strings コマンドライン引数に入力した文字列を一文字ずつ取得し、その文字を0x75でand処理し、string1と比較。さらに、取得した文字を0xebでand処理し、string2と比較してる。 string1="atd4...." string2="c\` b..." ```python a="atd4`qdedtUpetepqeUdaaeUeaqau" b="c\`b bk\'..."#snip for i in range(len(a)): for j in range(0xff): if (ord(a[i])) == j&0x75 and ord(b[i]) ==j&0xeb: flag +=chr(j) break print(flag) ``` ### yakisoba スパゲッティコードです。 解析: radare2;objdump;ghidra コードを見てると、入力した文字列をif文でcheckして間違っていたら早期returnさせるコードのようなのでret命令が踏まれないような数値を見つけます。(人力でやりました) あとでわかったのですが、ghidraのdecompileにて見るとすぐにわかるみたいですif argv[N]!=0x33などでリターンさせないようにしてるみたいです。 > anger使えばよかったです ## pwn ### beginners stack 解析なし 実際に動かすとoverflowさせてreturnアドレスを書き換えるだけだと一目瞭然なのでreturnアドレスまでのoffsetをみて、書き換えるだけです。 また、書き換えるアドレスも与えられており、特に考えずreturnアドレス位置にwin関数のアドレスを入れます > overflowの勉強になるので一度やることをお勧めします ### beginners heap binaryが配られていないので解析できませんがこちらもwin関数を呼べばいいみたいです。 __free_hook関数ポインタとwin関数のアドレスが始めに与えられます。 ``` 1. read(0, A, 0x80); 2. B = malloc(0x18); read(0, B, 0x18); 3. free(B); B = NULL; 4. Describe heap 5. Describe tcache (for size 0x20) 6. Currently available hint ``` のコマンドがあり、新しくmallocができたり、Aに書き込んだりできるみたいです。 最初にA=malloc(0x18)してるのに、書き込みが0x80byteなのでoverflowします。 ### childheap ``` 0x559b1ae31900: 0x0000000000000000 0x0000000000000000 0x559b1ae31910: 0x0000000000000000 0x0000000000000000 0x559b1ae31920: 0x0000000000000000 0x0000000000000000 0x559b1ae31930: 0x0000000000000000 0x0000000000000000 0x559b1ae31940: 0x0000000000000000 0x0000000000000021 0x559b1ae31950: 0x4141414141414141 0x4141414141414141 0x559b1ae31960: 0x4141414141414141 0x0000000000000100 0x559b1ae31970: 0x0000559b1ae31840 0x0000559b1ae31010 0x559b1ae31980: 0x4141414141414141 0x4141414141414141 0x559b1ae31990: 0x4141414141414141 0x4141414141414141 0x559b1ae319a0: 0x0000559b1ae319b0 0x0000559b1ae319b0 <= fake chunkを指している(loop) 0x559b1ae319b0: 0x0000000000000000 0x0000000000000100 <= fake chunk 0x559b1ae319c0: 0x0000559b1ae31990 0x0000559b1ae31990 <=どこさしてんねん 0x559b1ae319d0: 0x0000000000000000 0x0000000000000000 0x559b1ae319e0: 0x0000000000000000 0x0000000000000000 0x559b1ae319f0: 0x0000000000000000 0x0000000000000000 0x559b1ae31a00: 0x0000000000000000 0x0000000000000000 0x559b1ae31a10: 0x0000000000000000 0x0000000000000000 0x559b1ae31a20: 0x0000000000000000 0x0000000000000000 0x559b1ae31a30: 0x0000000000000000 0x0000000000000000 0x559b1ae31a40: 0x0000000000000000 0x0000000000000000 0x559b1ae31a50: 0x0000000000000000 0x0000000000000000 0x559b1ae31a60: 0x0000000000000000 0x0000000000000000 0x559b1ae31a70: 0x0000000000000000 0x0000000000000041 0x559b1ae31a80: 0x0000000000000000 0x0000559b1ae31010 0x559b1ae31a90: 0x4141414141414141 0x4141414141414141 0x559b1ae31aa0: 0x4141414141414141 0x4141414141414141 0x559b1ae31ab0: 0x0000000000000100 0x0000000000000100 0x559b1ae31ac0: 0x0000000000000000 0x0000559b1ae31010 0x559b1ae31ad0: 0x0000000000000000 0x0000000000000000 0x559b1ae31ae0: 0x0000000000000000 0x0000000000000000 0x559b1ae31af0: 0x0000000000000000 0x0000000000000000 0x559b1ae31b00: 0x0000000000000000 0x0000000000000000 0x559b1ae31b10: 0x0000000000000000 0x0000000000000000 0x559b1ae31b20: 0x0000000000000000 0x0000000000000000 0x559b1ae31b30: 0x0000000000000000 0x0000000000000000 0x559b1ae31b40: 0x0000000000000000 0x0000000000000000 0x559b1ae31b50: 0x0000000000000000 0x0000000000000000 0x559b1ae31b60: 0x0000000000000000 0x0000000000000000 0x559b1ae31b70: 0x0000000000000000 0x0000000000000000 0x559b1ae31b80: 0x0000000000000000 0x0000000000000000 0x559b1ae31b90: 0x0000000000000000 0x0000000000000000 0x559b1ae31ba0: 0x0000000000000000 0x0000000000000000 0x559b1ae31bb0: 0x0000000000000000 0x0000000000000000 0x559b1ae31bc0: 0x0000000000000000 0x0000000000000031 0x559b1ae31bd0: 0x0000000000000000 0x0000000000000021 0x559b1ae31be0: 0x0000000000000000 0x0000000000000021 0x559b1ae31bf0: 0x0000000000000000 0x0000000000020411 ``` next ``` 0x559b1ae31910: 0x0000000000000000 0x0000000000000000 0x559b1ae31920: 0x0000000000000000 0x0000000000000000 0x559b1ae31930: 0x0000000000000000 0x0000000000000000 0x559b1ae31940: 0x0000000000000000 0x0000000000000021 0x559b1ae31950: 0x4141414141414141 0x4141414141414141 0x559b1ae31960: 0x4141414141414141 0x0000000000000100 0x559b1ae31970: 0x0000559b1ae31840 0x0000559b1ae31010 0x559b1ae31980: 0x4141414141414141 0x4141414141414141 0x559b1ae31990: 0x4141414141414141 0x4141414141414141 0x559b1ae319a0: 0x0000559b1ae31990 0x0000559b1ae31990 0x559b1ae319b0: 0x0000000000000000 0x0000000000000201 <= malloc_consolidateで統合された 0x559b1ae319c0: 0x00007fad892aeca0 0x00007fad892aeca0 <= main_arenaのアドレス 0x559b1ae319d0: 0x0000000000000000 0x0000000000000000 0x559b1ae319e0: 0x0000000000000000 0x0000000000000000 0x559b1ae319f0: 0x0000000000000000 0x0000000000000000 0x559b1ae31a00: 0x0000000000000000 0x0000000000000000 0x559b1ae31a10: 0x0000000000000000 0x0000000000000000 0x559b1ae31a20: 0x0000000000000000 0x0000000000000000 0x559b1ae31a30: 0x0000000000000000 0x0000000000000000 0x559b1ae31a40: 0x0000000000000000 0x0000000000000000 0x559b1ae31a50: 0x0000000000000000 0x0000000000000000 0x559b1ae31a60: 0x0000000000000000 0x0000000000000000 0x559b1ae31a70: 0x0000000000000000 0x0000000000000041 <=ここが重要で正規のchunkが統合されたchunk内にある状態 0x559b1ae31a80: 0x0000000000000000 0x0000559b1ae31010 <=fd pointerを任意のアドレスに書き換えれば 0x559b1ae31a90: 0x4141414141414141 0x4141414141414141 0x559b1ae31aa0: 0x4141414141414141 0x4141414141414141 0x559b1ae31ab0: 0x0000000000000100 0x0000000000000100 <= prev_sizeが0x100 0x559b1ae31ac0: 0x0000000000000000 0x0000000000000021 0x559b1ae31ad0: 0x0000000000000000 0x0000000000000021 0x559b1ae31ae0: 0x0000000000000000 0x0000000000000021 0x559b1ae31af0: 0x0000000000000000 0x0000000000000021 0x559b1ae31b00: 0x0000000000000000 0x0000000000000021 0x559b1ae31b10: 0x0000000000000000 0x0000000000000021 0x559b1ae31b20: 0x0000000000000000 0x0000000000000021 0x559b1ae31b30: 0x0000000000000000 0x0000000000000021 0x559b1ae31b40: 0x0000000000000000 0x0000000000000021 0x559b1ae31b50: 0x0000000000000000 0x0000000000000021 0x559b1ae31b60: 0x0000000000000000 0x0000000000000021 0x559b1ae31b70: 0x0000000000000000 0x0000000000000021 0x559b1ae31b80: 0x0000000000000000 0x0000000000000021 0x559b1ae31b90: 0x0000000000000000 0x0000000000000021 0x559b1ae31ba0: 0x0000000000000000 0x0000000000000021 0x559b1ae31bb0: 0x0000000000000200 0x0000000000000020 <= backword チェックが入った 0x559b1ae31bc0: 0x0000000000000000 0x0000000000000031 0x559b1ae31bd0: 0x0000000000000000 0x0000000000000021 0x559b1ae31be0: 0x0000000000000000 0x0000000000000021 0x559b1ae31bf0: 0x0000000000000000 0x0000000000020411 ``` 今回の学びとしては pointerが一つだけを保持する問題であってもサイズを書き換えられるのであれば、heapリークはできる。 また、prev sizeとprev_inuseがクリアできるのであれば、統合を利用してlibcをリークできる。 加えて、統合の際にtcacheにつないだchunkをまたがって統合できるのであれば、任意のアドレスを確保できる。 ただ、unsorted bin(all)がtcacheよりも優先してメモリを返してくれるのは知らなかった。 これに関しては、unsorted binが使われるのではなく、要求サイズchunkがtchacheに無い場合にunsortedbinから切り出して使うみたいです。