flag 只对创建者 lotto_pwn 和 root 可读,而我们登录的用户是 lotto,无读权限。lotto 对 lotto_pwn 和 lotto 开放读和执行权限,而且权限里面有 s,因此 lotto 用户在执行这个文件时会被赋予与用户 lotto_pwn 相同权限。
我们的目标是执行 system("/bin/cat flag"),这要求 match 的值等于 6 。
由
知,lotto 数组中的每一个数都要与 submit 数组中的每一个数比较,如果相等,则 match++ ,submit 的值是我们手动输入的,他是字符型数组,lotto 的值是 /dev/urandom 生成的伪随机数,其 ASCII 值属于 1 ~ 45。其中可打印字符包括 !"#$%&'()+,- 十三个。
此处本应是只比较 6 次,这里写成了比较 36 次。*
所以我们可以输入 6 个相同的数,这样次要生成的随机数中存在一个与输入的数相等的,match 的值就为 6
红框内为 flag
本地执行
本地执行时需建立 flag 的软链接
remote
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
;
}
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"
);
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)