2021西湖论剑-wp

Posted 满天星ak

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021西湖论剑-wp相关的知识,希望对你有一定的参考价值。

2021西湖论剑-wp

前言

全靠大佬打,我是划水的。

灏妹的web

页面开发中
Dirsearch扫一下,idea泄露

ezupload

查看页面源代码,发现提示

?source=1

发现使用_FILE进行上传,构造上传表单

访问并随便上传一个文件,放到bp里回显no
查看源码最后一个else,在此情况进行渲染temper/index.latte,同时文件也被写入temper。也就是我们上传index.latte的文件。

waf测试
if “$nl /f*>1”/if


然后上传,最后访问url/1。

密码人集合

nc连接

可知为数独
https://www.jb51.net/article/110940.htm 借此脚本

#coding=utf-8

import datetime

class solution(object):

def __init__(self,board):

self.b = board

self.t = 0

def check(self,x,y,value):#检查每行每列及每宫是否有相同项

for row_item in self.b[x]:

if row_item == value:

return False

for row_all in self.b:

if row_all[y] == value:

return False

row,col=x/3*3,y/3*3

row3col3=self.b[row][col:col+3]+self.b[row+1][col:col+3]+self.b[row+2][col:col+3]

for row3col3_item in row3col3:

if row3col3_item == value:

return False

return True

def get_next(self,x,y):#得到下一个未填项

for next_soulu in range(y+1,9):

if self.b[x][next_soulu] == 0:

return x,next_soulu

for row_n in range(x+1,9):

for col_n in range(0,9):

if self.b[row_n][col_n] == 0:

return row_n,col_n

return -1,-1 #若无下一个未填项,返回‐1

def try_it(self,x,y):#主循环

if self.b[x][y] == 0:

for i in range(1,10):#从1到9尝试

self.t+=1

if self.check(x,y,i):#符合 行列宫均无条件 的

self.b[x][y]=i #将符合条件的填入0格

next_x,next_y=self.get_next(x,y)#得到下一个0格

if next_x == -1: #如果无下一个0格

return True #返回True

else: #如果有下一个0格,递归判断下一个0格直到填满数独

end=self.try_it(next_x,next_y)

if not end: #在递归过程中存在不符合条件的,即 使try_it函数返回None的项

self.b[x][y] = 0 #回朔到上一层继续

else:

return True

def start(self):

begin = datetime.datetime.now()

if self.b[0][0] == 0:

self.try_it(0,0)

else:

x,y=self.get_next(0,0)

self.try_it(x,y)

for i in self.b:

print i

end = datetime.datetime.now()

print '\\ncost time:', end - begin

print 'times:',self.t

return



s=solution([[3,0,1,0,5,8,0,0,7],

[4,0,0,0,0,0,0,3,0],

[0,0,0,0,2,0,0,0,0],

[9,8,0,3,0,0,0,0,6],

[0,0,6,0,0,0,0,0,0],

[0,0,0,0,0,0,7,8,0],

[5,0,0,0,6,0,9,0,8],

[8,0,0,0,0,0,0,0,1],

[0,0,0,0,0,0,0,0,0]])

s.start()

西湖论剑我要拿第一

1 234 5678 9 依次代替成数字

得出结果,再转回文字

unknown_dsa

先来求一下佩尔方程,得解是ul 和 vl:
ul[i] ^ 2 - wl[i] \\times vl[i]^2 == 1

Python脚本

wl = [3912956711, 4013184893, 3260747771]

ul = []

vl = []

def pell(N, try_num):

cf = continued_fraction(sqrt(N))

for i in range(try_num):

denom = cf.denominator(i)

numer = cf.numerator(i)

if numer2 - N * denom2 == 1:

return numer, denom

return None, None

for N in wl:

ult, vlt = pell(N, 10000)

ul.append(ult)

vl.append(vlt)

print(ul)

print(vl)

2.拿到ul 和 vl,知道c11和c12,得到m1和m2

m1=crt(c11,ui)

m1,_=gmpy2.iroot(m1,7)

Print(long_to_buyes(m1))

m2=crt(c12,v1)

m2,_=gmpy2.iroot(m2,7)

Print(long_to_buyes(m2))

求p和q,已知 p ∗ q p * q pq 和 $(p-1)

脚本如下

Import gmpy2

n=852589223779928796266540600421678790889067284911682578924216186052590393595645322161563386615512475256 x=211158499061801396563106646074584256376705200819832482589841660262228987535050089041366888200757204110 Delta=1+4*n*x

delta_sqrt, _ = gmpy2.iroot(delta, 2)

p = (1 + delta_sqrt) // 2

q = n // p

print(p)

print(q)

计算x1和x2就行。

s1 = (hm1 + x1*r1) * invert(k, q) % q

s2 = (hm2 + x1*r1) * invert(k, q) % q

TacticalArmed

打开exe,程序用了二进制文件的数据动态来构建机器码

首先来提取机器码

import pefile, binascii, struct, mmap

from iced_x86 import *

from typing import Dict, Sequence

from types import ModuleType

flag = b"0" * 8

ida_off = 0x401a00

bin_file = open('./TacticalArmed.exe', 'rb')

bin_map = mmap.mmap(bin_file.fileno(), 0, access=mmap.ACCESS_READ)

sizes_raw = bin_map[0x405220 - ida_off:0x405220 - ida_off + 34 * 4]

sizes = [struct.unpack('@I', sizes_raw[i:i+4])[0] for i in range(0, len(sizes_raw), 4)]

template_base = 0x405010 - ida_off

dw_4052A8_base = 0x4052A8 - ida_off

size = 0

v17 = 0

counter = 0

template_offset = template_base

def sub_4011F0(b_arr, counter, offset):

i = 0

while b_arr[i] != 0:

i += 1

dw = struct.unpack('@I', bin_map[dw_4052A8_base + counter * 4:dw_4052A8_base + counter * 4 + 4])[0]

assert dw >= 0

v5 = dw % 0x10

v4 = dw >> 4

if v4 == 1:

b_arr[i:i+4] = struct.pack('@I', 0x405648 + 4 * (v5 + 2 * offset))

elif v4 == 2:

b_arr[i:i+4] = struct.pack('@I', 0x405000 + 4 * v5)

elif v4 == 3:

b_arr[i:i+4] = struct.pack('@I', 0x405748)

formatter = Formatter(FormatterSyntax.INTEL)

def create_enum_dict(module: ModuleType) -> Dict[int, str]:

return module.__dict__[key]:key for key in module.__dict__ if isinstance(module.__dict__[key], int)

CODE_TO_STRING: Dict[Code_, str] = create_enum_dict(Code)

def code_to_string(value: Code_) -> str:

s = CODE_TO_STRING.get(value)

if s is None:

return str(value) + " /*Code enum*/"

return s

REGISTER_TO_STRING: Dict[Register_, str] = create_enum_dict(Register)

def register_to_string(value: Register_) -> str:

s = REGISTER_TO_STRING.get(value)

if s is None:

return str(value) + " /*Register enum*/"

return s

OP_CODE_OPERAND_KIND_TO_STRING: Dict[OpCodeOperandKind_, str] = create_enum_dict(OpCodeOperandKind)

def op_code_operand_kind_to_string(value: OpCodeOperandKind_) -> str:

s = OP_CODE_OPERAND_KIND_TO_STRING.get(value)

if s is None:

return str(value) + " /*OpCodeOperandKind enum*/"

return s

MNEMONIC_TO_STRING: Dict[Mnemonic_, str] = create_enum_dict(Mnemonic)

def mnemonic_to_string(value: Mnemonic_) -> str:

s= MNEMONIC_TO_STRING.get(value) if s is None:

return str(value) + " /*Mnemonic enum*/" return s

def format_mem(offset, is_lhs):

if offset == 0x405748:

return "TMP", False

elif offset >= 0x405648 and offset < 0x405748:

off = offset - 0x405648

if is_lhs:

return "INPUT[%d:%d]" % (off, off + 4), True

else:

return "struct.unpack('@i', INPUT[%d:%d])[0]" % (off, off + 4), False

elif offset >= 0x405000 and offset <= 0x40500C:

#return 

#0x405000: "0x7CE45630",

#0x405004: "0x58334908",

#0x405008: "0x66398867",

#0x40500C: "0xC35195B1",

#[offset]

return 

0x405000: "0x22836719",

0x405004: "0xA5978C21",

0x405008: "0x79573824",

0x40500C: "0x330B55EF",

[offset], False

else:

raise ValueError("Unknown memory region")

out = open("sdisasm.py", 'w')

out.writelines([

"import struct\\n",

"TMP = 0\\n",

"INPUT = bytearray(b\\"\\\\x00\\" * )\\n".format(len(flag))

])

out_code = open("shellcode.bin", 'wb')

for current_off_1 in range(len(flag) >> 3):

size = 0

for j in range(34):

while size > 0:

op_buf = bytearray(b"\\x00" * 16)

# print(size)

op_buf[:size] = bin_map[template_offset:template_offset + size]

sub_4011F0(op_buf, counter, current_off_1)

out_code.write(op_buf[:size])

op_buf[size] = 0xc3

decoder = Decoder(32, op_buf[:size + 1], ip=0x405010)

for instr in decoder:

info_factory = InstructionInfoFactory()

info = info_factory.info(instr)

op_code = instr.op_code()

disasm = formatter.format(instr)

start_index = instr.ip - 0x405010

bytes_str = op_buf[start_index:start_index + instr.len].hex().upper()

#print(f"bytes_str:20 disasm")

#print(code_to_string(instr.code))

mnemonic = mnemonic_to_string(instr.mnemonic)

lhs = None

lhs_kind = op_code_operand_kind_to_string(op_code.op_kind(0))

lhs_reg = register_to_string(instr.op0_register)

lhs_is_buffer = False

if lhs_kind == "EAX":

lhs = "EAX"

elif lhs_kind == "R32_REG":

lhs = lhs_reg

elif lhs_kind == "R32_OR_MEM":

if lhs_reg != "NONE":

lhs = lhs_reg

else:

assert(len(info.used_memory()) == 1)

lhs,lhs_is_buffer = format_mem(info.used_memory()[0].displacement, True)

elif lhs_kind == "MEM_OFFS":

assert(len(info.used_memory()) == 1)

lhs, lhs_is_buffer = format_mem(info.used_memory()[0].displacement, True)

else:

raise Exception(f"Unknown lhs kind: lhs_kind")

rhs = None

rhs_kind = op_code_operand_kind_to_string(op_code.op_kind(1))

rhs_reg = register_to_string(instr.op1_register)

rhs_is_buffer = False

if rhs_kind == "EAX":

rhs = "EAX"

elif rhs_kind == "R32_REG":

rhs = rhs_reg

elif rhs_kind == "R32_OR_MEM":

if rhs_reg != "NONE":

rhs = rhs_reg

else:

assert(len(info.used_memory()) == 1)

rhs, rhs_is_buffer = format_mem(info.used_memory()[0].displacement, False)

elif rhs_kind == "MEM_OFFS":

assert(len(info.used_memory()) == 1)

rhs, rhs_is_buffer = format_mem(info.used_memory()[0].displacement, False)

elif rhs_kind == "IMM8":

rhs = hex(instr.immediate8)

elif rhs_kind == "IMM32":

rhs = hex(instr.immediate32)

else:

raise Exception(f"Unknown rhs kind: rhs_kind")

if lhs_is_buffer and not rhs_is_buffer:

rhs = "struct.pack('@i', )".format(rhs)

line = 

'MOV': 'lhs = rhs',

#'ADD': 'lhs = (lhs + rhs) & 0xFFFFFFFF',

#'SUB': 'lhs = (lhs - rhs) & 0xFFFFFFFF',

#'SHR': 'lhs = (lhs >> rhs) & 0xFFFFFFFF',

#'SHL': 'lhs = (lhs << rhs) & 0xFFFFFFFF',

#'XOR': 'lhs = (lhs ^ rhs) & 0xFFFFFFFF', 'ADD': 'lhs = lhs + rhs',

'SUB': 'lhs = lhs - rhs',

'SHR': 'lhs = lhs >> rhs',

'SHL': 'lhs = lhs << rhs',

'XOR': 'lhs = lhs ^ rhs',

[mnemonic].format(lhs=lhs, rhs=rhs)

out.write(line + "\\n")

break

counter += 1

template_offset += 0x10

size = sizes[v17]

v17 += 1

counter = 0

template_offset = template_base

size = sizes[0]

v17 = 1

out.write("# ==\\n")

print("# ======")

提取成功,然后根据迭代

ECX = TMP

ECX = ECX - 0x7e5a96d2

TMP = ECX

EDX = struct.unpack('@i', INPUT[4:8])[0]

EDX = EDX >> 0x5

EAX = 0xA5978C21

EAX = EAX + EDX

ECX = TMP

ECX = ECX + struct.unpack('@i', INPUT[4:8])[0]

EAX = EAX ^ ECX

EDX = struct.unpack('@i', INPUT[4:8])[0]

EDX = EDX << 0x4

ECX = 0x22836719

ECX = ECX + EDX

EAX = EAX ^ ECX

EDX = struct.unpack('@i', INPUT[0:4])[0]

EDX = EDX + EAX

INPUT[0:4] = struct.pack('@i', EDX)

EAX = struct.unpack('@i', INPUT[0:4])[0]

EAX = EAX >> 0x5

ECX = 0x330B55EF

ECX = ECX + EAX

EDX = TMP

EDX = EDX + struct.unpack('@i', INPUT[0:4])[0]

ECX = ECX ^ EDX

EAX = struct.unpack('@i', INPUT[0:4])[0]

EAX = EAX << 0x4

EDX = 0x79573824

EDX = EDX + EAX

ECX = ECX ^ EDX

EAX = struct.unpack('@i', INPUT[4:8])[0]

EAX = EAX + ECX

INPUT[4:8] = struct.pack('@i', EAX)

最后解密,我们尝试TEA算法进行解密

static uint32_t sum = 0x8F9CCAA6; // 动调获得

void encrypt (uint32_t v[2], const uint32_t k[4]) 

uint32_t v0=v[0], v1=v[1], sum=0, i;	/* set up */

uint32_t delta=0x7e5a96d2;	/* a key schedule constant */

uint32_t k0=k[0]以上是关于2021西湖论剑-wp的主要内容,如果未能解决你的问题,请参考以下文章

2021-西湖论剑-Web-Writeup

2021-西湖论剑-Web-Writeup

西湖论剑WP

[西湖论剑]yuas的秘密wp

2019西湖论剑web wp

2019 安恒周周练西湖论剑特别版 pwn部分wp