#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>


unsigned char submit[6];


void play(){

int i;

printf("Submit your 6 lotto bytes : ");

fflush(stdout);


int r;

r = read(0, submit, 6);


printf("Lotto Start!\n");

//sleep(1);


// generate lotto numbers

int fd = open("/dev/urandom", O_RDONLY);

if(fd==-1){

printf("error. tell admin\n");

exit(-1);

}

unsigned char lotto[6];

if(read(fd, lotto, 6) != 6){

printf("error2. tell admin\n");

exit(-1);

}

for(i=0; i<6; i++){

lotto[i] = (lotto[i] % 45) + 1; // 1 ~ 45

}

close(fd);

// calculate lotto score

int match = 0, j = 0;

for(i=0; i<6; i++){

for(j=0; j<6; j++){

if(lotto[i] == submit[j]){

match++;

}

}

}


// win!

if(match == 6){

system("/bin/cat flag");

}

else{

printf("bad luck...\n");

}


}


void help(){

printf("- nLotto Rule -\n");

printf("nlotto is consisted with 6 random natural numbers less than 46\n");

printf("your goal is to match lotto numbers as many as you can\n");

printf("if you win lottery for *1st place*, you will get reward\n");

printf("for more details, follow the link below\n");

printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01\n\n");

printf("mathematical chance to win this game is known to be 1/8145060.\n");

}


int main(int argc, char* argv[]){


// menu

unsigned int menu;


while(1){


printf("- Select Menu -\n");

printf("1. Play Lotto\n");

printf("2. Help\n");

printf("3. Exit\n");


scanf("%d", &menu);


switch(menu){

case 1:

play();

break;

case 2:

help();

break;

case 3:

printf("bye\n");

return 0;

default:

printf("invalid menu\n");

break;

}

}

return 0;

}




이번은 그냥 gdb로 무식하게 열어보았다.




cmp하는 곳에 BP를 걸고 무작정 돌려봣는데, 아무리 돌려도 한 값은 바뀌지 않았다.

즉, 한 숫자를 맞추면 6개 다 맞추는게 된다는 것이었다.


그래서 그냥 0x12로 하고 여러번 실행해 보았다.



from pwn import *


r = process('./lotto')


context.log_level='debug'

r.recv(1024)

r.sendline('1')

r.send('\x12\x12\x12\x12\x12\x12')


r.interactive()



그냥 단순하게 \x12를 연속으로 6개 전송하는 py코드를 짜고,

실행 하였다.


물론 실행 파일, flag는 tmp에 심볼릭 링크를 만들어서 실행했다.




Flag를 땄다.

'pwnable > Toddler's Bottle' 카테고리의 다른 글

[Toddle's Bottle] cmd2  (0) 2018.05.31
[Toddler's Bottle] cmd1  (0) 2018.05.29
[Toddler's Bottle] blackjack  (0) 2018.05.29
[Toddle's Bottle] coin1  (0) 2018.05.29
[Toddler's Bottle] shellshock  (0) 2018.05.28
블로그 이미지

천재보다는 범재

,

http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html


이번엔 코드를 따로 주었다.


사실 한참 읽어봐야 하지만, 딱 눈에 띄는 부분이 있다.


보통 조건이 만족될때까지 while로 계속 돌릴텐데, 이 경우에는 bet한 금액이 cash보다 크다고 해도, 입력을 한번만 받고 만다.

즉 한번 일부러 큰 수를 넣고 그 다음에 다시 더 큰 수를 넣으면 그대로 들어간다는 뜻이다.


I like to give my flags to millionares.

how much money you got?


라고 하니, 많은 금액을 따보자.

BET를 크게 넣고,  단 한번만 이겨서 인생 역전...!?


bet로는 999999999 정도를 넣었다.



여러번 도산하면서 딱 한번 이겨서 Flag를 땄다.

'pwnable > Toddler's Bottle' 카테고리의 다른 글

[Toddler's Bottle] cmd1  (0) 2018.05.29
[Toddler's Bottle] lotto  (0) 2018.05.29
[Toddle's Bottle] coin1  (0) 2018.05.29
[Toddler's Bottle] shellshock  (0) 2018.05.28
[Toddler's Bottle] mistake  (0) 2018.05.28
블로그 이미지

천재보다는 범재

,

coin1은 코드가 없다.


Mommy, I wanna play a game!

(if your network response time is too slow, try nc 0 9007 inside pwnable.kr server)


Running at : nc pwnable.kr 9007



라는 문자열만 주어져 있다.


연결하면


위조 동전을 찾아라. 라고 한다. 진짜 동전은 무게가 10이고, 위조동전은 9이다. 따라서 그리고 위조동전을 100개 찾으면 상을 준다고 한다. Flag이겠지..


나는

10 단위로 잘라 bruteforce를 해, 뒷자리가 9일 때 멈춘 후, 직접 찍어 맞추려고 했는데, 생각보다 찾을 확률이 너무 저조했다. 이 확률로 100번을 뚫을 수 있으면 그날에 로또를 사도 될 거라 생각할 정도였다.



from pwn import *

from operator import eq


context.log_level='debug'



flag=0


search='9'

search2 = "Correct! (0)"


r = remote("pwnable.kr", 9007)

print(r.recv(2048))

sleep(3.3)

r.recv(100)


i=20d

while 1:

payload=""

sleep(0.5)

for j in range(10):

payload += " " + str(i+j)

r.sendline(payload)

i+=10

weight = r.recv(10)

if search in weight :

i-=10

print i

break



r.interactive()




그래서 다른방법을 고민하다가 결국 다른 사람의 것을 참고했다.


위 스샷의 경우 N은 479이다. 479는 2^8과 2^9 의 사이이다. 즉 2로 나눠가면서 어느

쪽에 있는지만 찾아내면 된다.


밑의 코드는 (http://chaneyoon.tistory.com/192) 에 있다.


from pwn import *

import time

import sys


host = '0'

port = 9007


r = remote(host, port)

time.sleep(3)           # wait for 3 sec.


print r.recv()


cnt = 0

for i in range(100):

    r.recvuntil('N=')

    n = int( r.recvuntil(' ') )

    r.recvuntil('C=')

    c = int( r.recv() )

    

    st = 1

    des = n

    t = 0

    while(1):

        

        message = ''

        

        if(st > des):

            break

        

        message = ''

        for i in range(st, (st + des) // 2 + 1):

            message += '{0} '.format(i) 

        

        print "[-] guess : {0}".format(message)

        x = r.sendline(message)

        result = r.recv()

        

        print "[*] result : {0}".format(result)


        if result.find('Correct') > -1:

            t = 1

            break

        elif result[0] == 'N':

            des = n

        elif result.find('error') > -1:

            break

        elif result.find('time') > -1:

            print "\n\n[x] time expired.."

            sys.exit(1)

        elif int(result) % 10 != 0:

            des = (st + des)//2

        else:

            st = (st+des)//2 + 1

    if(t == 0):

        r.sendline(str(st))

        correctmsg = r.recv()

    cnt += 1

    print "[+] count : {0}\n".format(cnt)


flag = r.recv()

print "\n\n[*] FLAG : {0}".format(flag)




python코드가 너무 고급져서 해석하기 힘들다.


하지만 잘 보면, N=[] 부분에서 숫자를 받아와서, 그것을 message에 넣고, send로 보낸다.

그 후, recv를 통해 값을 받아오는데, 이것이 Correct, error, time 을 읿력받으면 break한다. 그렇지 않다면 2를 나눠가면서 계속 좁혀나간다.


한번 성공할때마다 cnt++를 하며 총 100번 되면 r.recv()를 통해서 FLAG를 받아온다.





내가 직접 코드를 짤 수 있게 될때까지 코드를 좀 더 분석해 봐야겠다.

'pwnable > Toddler's Bottle' 카테고리의 다른 글

[Toddler's Bottle] lotto  (0) 2018.05.29
[Toddler's Bottle] blackjack  (0) 2018.05.29
[Toddler's Bottle] shellshock  (0) 2018.05.28
[Toddler's Bottle] mistake  (0) 2018.05.28
[Toddler's Bottle] leg  (0) 2018.05.28
블로그 이미지

천재보다는 범재

,