BaseCTF2024 Reverse
[Week1] Ez Xor
这里是加密后的东西,由于是局部变量,直接变成一坨了,我们把它弄出来就行,或者直接动态调试,从hex-view里面找,也是很方便的。
from regadgets import *
# data
enc = qword2byte([0x1D0B2D2625050901, 0x673D491E20317A24, 0x34056E2E2508504D])
enc += b"\"@;%"
assert len(enc) == 28
# keystream
k = b'Xor'
keyStream = bytes([i ^ k[i % len(k)] for i in range(len(enc))])
# xor
print(bxor(enc, keyStream[::-1]))
# b'BaseCTF{X0R_I5_345Y_F0r_y0U}'
[Week1] You are good at IDA
Y0u_4Re_
900d_47_
id4BaseCTF{Y0u_4Re_900d_47_id4}
[Week1] BasePlus
Encode 里面经过分析是一个Base64 encode
Secret是/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC
也就是一个换表Base64,不过base64里面偷偷给你异或了一个0xE,这个要注意
from regadgets import *
enc = b'lvfzBiZiOw7<lhF8dDOfEbmI]i@bdcZfEc^z>aD!'
k = 0xe
dec = decode_b64(bxor(enc, [k for _ in range(len(enc))]).decode(),
'/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC')
print(dec)
# b'BaseCTF{BA5e_DEcoD1N6_sEcr3t}\x00'
[Week1] UPX mini
UPX 解压
base64_encode,名字没有清理掉,而且进去是标准base64
from regadgets import *
enc = 'QmFzZUNURntIYXYzX0BfZzBvZF90MW0zISEhfQ=='
dec = decode_b64(enc)
print(dec)
# b'BaseCTF{Hav3_@_g0od_t1m3!!!}'
[Week1] ez_maze
进去之后分析一下,把一些字符还原了,wasd,这几个分别是上左下右,看起来是没问题的
显然迷宫是用一个数组进行存储,pos % 15 == 14
可以知道迷宫行宽15(因为pos从0开始), pos > 209
可知道迷宫总共210个数,也就是15*14的迷宫
然后如果是y就是终点,如果是$就是invalid(墙壁,不能走)。
我们提取出来,看一看
>>> a = "x$$$$$$$$$$$$$$&&&&&&$$$$$$$$$&$&$$&$$&&&&&$$&$&$$$&&$$$$&$$&$$$&&&$$$$$&$$&$$$&$&&$&$$$$$&$$$&$&$$&&&$$$&&&&&$&&&&$&$$$$$$$$$&&&&&&$$$$$$$$$&$$$$$$$$$$$&&&&$$&&&$$$$$$&&&&&&&$$$$$$$$$$$$$$&$$&$$$$$$$$$$$&$&$$$$$$$$$&&&&&&&&y"
>>>
>>> for i in range(0, len(a), 15):
... print(a[i:i+15])
...
x$$$$$$$$$$$$$$
&&&&&&$$$$$$$$$
&$&$$&$$&&&&&$$
&$&$$$&&$$$$&$$
&$$$&&&$$$$$&$$
&$$$&$&&$&$$$$$
&$$$&$&$$&&&$$$
&&&&&$&&&&$&$$$
$$$$$$&&&&&&$$$
$$$$$$&$$$$$$$$
$$$&&&&$$&&&$$$
$$$&&&&&&&$$$$$
$$$$$$$$$&$$&$$
$$$$$$$$$&$&$$$
$$$$$$&&&&&&&&y
>>>
然后使用notepad++进行标记,手动走一下sssssssddddwwwddsssssssdddsssddddd
然后程序提示,flag是BaseCTF{md5(path)}
所以
from hashlib import md5
print(f"BaseCTF{{{md5(b'sssssssddddwwwddsssssssdddsssddddd').hexdigest()}}}")
# BaseCTF{131b7d6e60e8a34cb01801ae8de07efe}
[Week2] Ezpy
┌──(Administrator💀NullCafe)-[ base]-[~/Desktop/BaseCTF2024/Reverse/[Week2] Ezpy] 0ms
└─# python .\pyinstxtractor.py .\Ezpy.exe
[+] Processing .\Ezpy.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.9
[+] Length of package: 5835441 bytes
[+] Found 59 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: Ezpy.pyc
[!] Warning: This script is running in a different Python version than the one used to build the executable.
[!] Please run this script in Python 3.9 to prevent extraction errors during unmarshalling
[!] Skipping pyz extraction
[+] Found 81 files in PYZ archive
[+] Successfully extracted pyinstaller archive: .\Ezpy.exe
注意到
[!] Warning: This script is running in a different Python version than the one used to build the executable.
[!] Please run this script in Python 3.9 to prevent extraction errors during unmarshalling
[!] Skipping pyz extraction
这个其实是因为你python版本不对导致的,我们可以修改pyinstxtractor.py让它不跳过一些pyc的提取,也可以换python版本,我们这里为了反编译更完美,选择更换python版本。
我是用conda进行多版本python环境共存。
可以注意到,是python3.9.7,所以我们安装conda create -n py397 python=3.9.7
然后切换conda activate py397
┌──(Administrator💀NullCafe)-[ py397]-[~/Desktop/BaseCTF2024/Reverse/[Week2] Ezpy] 37ms
└─# python .\pyinstxtractor.py .\Ezpy.exe
[+] Processing .\Ezpy.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.9
[+] Length of package: 5835441 bytes
[+] Found 59 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: Ezpy.pyc
[+] Found 81 files in PYZ archive
[+] Successfully extracted pyinstaller archive: .\Ezpy.exe
You can now use a python decompiler on the pyc files within the extracted directory
这下就完美了,我们使用pycdc来反编译
# Source Generated with Decompyle++
# File: Ezpy.pyc (Python 3.9)
import Key
import sys
def init_Sbox(seed):
k_b = (lambda .0 = None: [ ord(seed[i % len(seed)]) for i in .0 ])(range(256))
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + k_b[i]) % 256
s[i] = s[j]
s[j] = s[i]
return s
def KeyStream(text, Sbox):
s = Sbox.copy()
(i, j) = (0, 0)
k = [
0] * len(text)
for r in range(len(text)):
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i] = s[j]
s[j] = s[i]
t = (s[i] + s[j]) % 256
k[r] = s[t] ^ Key.keykey[r % len(Key.keykey)]
return k
def Encrypt(text, seed):
Sbox = init_Sbox(seed)
key = KeyStream(text, Sbox)
enc = (lambda .0 = None: [ text[i] ^ key[i] for i in .0 ])(range(len(text)))
return bytes(enc)
enc = b'\xe6\xaeC~F\xf2\xe3\xbb\xac\x9a-\x02U\x85p\xeb\x19\xd1\xe4\xc93sG\xb0\xeb1\xb5\x05\x05\xc3\xd7\x00\x18+D\xbc\x0cO\x9em\xf1\xbd'
flag = input('Please input Your flag:')
flag = (lambda .0: [ ord(i) for i in .0 ])(flag)
flag = Encrypt(flag, Key.key)
if flag != enc:
print("It's not flag!")
continue
print('You are right!')
sys.exit(1)
continue
可以注意到,init_Sbox是RC4的init,KeyStream是在获取RC4的密钥流。
不过我们还需要知道Key.key,keykey这俩是什么
我们在子目录下找到Key.pyc,进行反编译
└─# C:\Users\Administrator\Desktop\Reverse\Python\pycdc\pycdc.exe .\Key.pyc
# Source Generated with Decompyle++
# File: Key.pyc (Python 3.9)
key = 'yOU_f1nd_m3'
keykey = [
66,
97,
115,
101]
exp
from regadgets import *
key = 'yOU_f1nd_m3'
keykey = [
66,
97,
115,
101]
enc = b'\xe6\xaeC~F\xf2\xe3\xbb\xac\x9a-\x02U\x85p\xeb\x19\xd1\xe4\xc93sG\xb0\xeb1\xb5\x05\x05\xc3\xd7\x00\x18+D\xbc\x0cO\x9em\xf1\xbd'
s = rc4_init(key.encode())
keystream = list(rc4_keystream(s, len(enc)))
keystream = bxor_cycle(keystream, keykey)
print(bxor(keystream, enc))
# b'BaseCTF{Y0u_kn0W_d3C0Mp1l4710N_PY_4ND_rC4}'
不过这里我推荐使用黑手办法
我们使用hypno进行注入
>>> from hypno import *
>>> code = """
... Sbox = init_Sbox(Key.key)
... keys = KeyStream("a"*len(enc), Sbox)
... print(keys)
... """
>>>
>>> inject_py(9024, code)
然后就能得到KeyStream,注入原理是,attach到Python39.dll然后
void run_python_code() {
if (PYTHON_CODE[0]) {
int saved_errno = errno;
PyGILState_STATE gstate = PyGILState_Ensure();
PyRun_SimpleString(PYTHON_CODE);
PyGILState_Release(gstate);
errno = saved_errno;
}
}
通过调用PyRun_SimpleString就可以执行代码注入。
然后我们继续
exp
from regadgets import *
enc = b'\xe6\xaeC~F\xf2\xe3\xbb\xac\x9a-\x02U\x85p\xeb\x19\xd1\xe4\xc93sG\xb0\xeb1\xb5\x05\x05\xc3\xd7\x00\x18+D\xbc\x0cO\x9em\xf1\xbd'
box = [164, 207, 48, 27, 5, 166, 165, 192, 245, 170, 88, 93, 62, 235, 64, 188, 70, 181, 215, 138, 3, 62, 55, 129, 135, 5, 130, 52, 53, 141, 136, 80, 65, 116, 112, 242, 72, 16, 236, 46, 197, 192]
print(bxor(enc, box))
# b'BaseCTF{Y0u_kn0W_d3C0Mp1l4710N_PY_4ND_rC4}'
注入应该是解决这种类型题目的最优雅的办法。
[Week2] RivestCipher
题目名字明示是rc4,但是我们还是看一看
main_main,是go编译的产物
由于ida对go的字符串支持不太行(因为go的字符串和rust的一样,都是连着的而不是x00截断)
我们直接看流程图
可以看到这里,mov ecx, 7代表后面的字符串长度7
所以字符串是BaseCTF
下面直接进rc4加密函数了,所以大概率是key
很清晰,所以我就直接写wp了(enc是后面的hex字符串 可以直接找到)
from regadgets import *
enc = bytes.fromhex('0ebb0c573dd548f3d2b2525f02895cd5275b6f6e5776538982ea41246dae8517')
s = rc4_init(b'BaseCTF')
print(rc4_crypt(s, enc))
# b'BaseCTF{go1@ng_!S_RuNNin9_RC4}\r\n'
[Week2] UPX
x64dbg 零帧起手,找到个
$rg7_dhd~Alidg+zeyhz`vnz_d,7sy0=
这时候我就已经猜到是魔改base64了,但是还是继续看看
果然找到base64表(& 0x3f)
A,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noX
from regadgets import *
print(decode_b64('$rg7_dhd~Alidg+zeyhz`vnz_d,7sy0=', 'A,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noX'))
# b'BaseCTF{UPX_1s_$o_e@sy}'
好吧,已经解出来了wmmm
[Week2] lk
z3基础题,直接搬运官方wp了(bushi
from z3 import *
a = [Int('a[%d]' % i) for i in range(21)]
s = Solver()
s.add(948 * a[20]
+ 887 * a[19]
+ 410 * a[18]
+ 978 * a[17]
+ 417 * a[16]
+ 908 * a[15]
+ 965 * a[14]
+ 987 * a[13]
+ 141 * a[12]
+ 257 * a[11]
+ 323 * a[10]
+ 931 * a[9]
+ 773 * a[8]
+ 851 * a[7]
+ 758 * a[6]
+ 891 * a[5]
+ 575 * a[4]
+ 616 * a[3]
+ 860 * a[2]
+ 283 * a[1] == 913686)
s.add( 938 * a[20]
+ 490 * a[19]
+ 920 * a[18]
+ 50 * a[17]
+ 568 * a[16]
+ 68 * a[15]
+ 35 * a[14]
+ 708 * a[13]
+ 938 * a[12]
+ 718 * a[11]
+ 589 * a[10]
+ 954 * a[9]
+ 974 * a[8]
+ 62 * a[7]
+ 580 * a[6]
+ 80 * a[5]
+ 111 * a[4]
+ 151 * a[3]
+ 421 * a[2]
+ 148 * a[1] == 630335)
s.add( 908 * a[20]
+ 590 * a[19]
+ 668 * a[18]
+ 222 * a[17]
+ 489 * a[16]
+ 335 * a[15]
+ 778 * a[14]
+ 622 * a[13]
+ 95 * a[12]
+ 920 * a[11]
+ 932 * a[10]
+ 892 * a[9]
+ 409 * a[8]
+ 392 * a[7]
+ 11 * a[6]
+ 113 * a[5]
+ 948 * a[4]
+ 674 * a[3]
+ 506 * a[2]
+ 182 * a[1] == 707525)
s.add( 479 * a[20]
+ 859 * a[19]
+ 410 * a[18]
+ 399 * a[17]
+ 891 * a[16]
+ 266 * a[15]
+ 773 * a[14]
+ 624 * a[13]
+ 34 * a[12]
+ 479 * a[11]
+ 465 * a[10]
+ 728 * a[9]
+ 447 * a[8]
+ 427 * a[7]
+ 890 * a[6]
+ 570 * a[5]
+ 716 * a[4]
+ 180 * a[3]
+ 571 * a[2]
+ 707 * a[1] == 724203)
s.add( 556 * a[20]
+ 798 * a[19]
+ 380 * a[18]
+ 716 * a[17]
+ 71 * a[16]
+ 901 * a[15]
+ 949 * a[14]
+ 304 * a[13]
+ 142 * a[12]
+ 679 * a[11]
+ 459 * a[10]
+ 814 * a[9]
+ 282 * a[8]
+ 49 * a[7]
+ 873 * a[6]
+ 169 * a[5]
+ 437 * a[4]
+ 199 * a[3]
+ 771 * a[2]
+ 807 * a[1] == 688899)
s.add( 465 * a[20]
+ 898 * a[19]
+ 979 * a[18]
+ 198 * a[17]
+ 156 * a[16]
+ 831 * a[15]
+ 856 * a[14]
+ 322 * a[13]
+ 25 * a[12]
+ 35 * a[11]
+ 369 * a[10]
+ 917 * a[9]
+ 522 * a[8]
+ 654 * a[7]
+ 235 * a[6]
+ 385 * a[5]
+ 469 * a[4]
+ 231 * a[3]
+ 496 * a[2]
+ 83 * a[1] == 604784)
s.add( 305 * a[20]
+ 928 * a[19]
+ 260 * a[18]
+ 793 * a[17]
+ 787 * a[16]
+ 708 * a[15]
+ 758 * a[14]
+ 236 * a[13]
+ 688 * a[12]
+ 747 * a[11]
+ 711 * a[10]
+ 195 * a[9]
+ 50 * a[8]
+ 648 * a[7]
+ 787 * a[6]
+ 376 * a[5]
+ 220 * a[4]
+ 33 * a[3]
+ 194 * a[2]
+ 585 * a[1] == 665485)
s.add( 767 * a[20]
+ 573 * a[19]
+ 22 * a[18]
+ 909 * a[17]
+ 598 * a[16]
+ 588 * a[15]
+ 136 * a[14]
+ 848 * a[12]
+ 964 * a[11]
+ 311 * a[10]
+ 701 * a[9]
+ 653 * a[8]
+ 541 * a[7]
+ 443 * a[6]
+ 7 * a[5]
+ 976 * a[4]
+ 803 * a[3]
+ 273 * a[2]
+ 859 * a[1] == 727664)
s.add( 776 * a[20]
+ 59 * a[19]
+ 507 * a[18]
+ 164 * a[17]
+ 397 * a[16]
+ 744 * a[15]
+ 377 * a[14]
+ 768 * a[13]
+ 456 * a[12]
+ 799 * a[11]
+ 9 * a[10]
+ 215 * a[9]
+ 365 * a[8]
+ 181 * a[7]
+ 634 * a[6]
+ 818 * a[5]
+ 81 * a[4]
+ 236 * a[3]
+ 883 * a[2]
+ 95 * a[1] == 572015)
s.add( 873 * a[20]
+ 234 * a[19]
+ 381 * a[18]
+ 423 * a[17]
+ 960 * a[16]
+ 689 * a[15]
+ 617 * a[14]
+ 240 * a[13]
+ 933 * a[12]
+ 300 * a[11]
+ 998 * a[10]
+ 773 * a[9]
+ 484 * a[8]
+ 905 * a[7]
+ 806 * a[6]
+ 792 * a[5]
+ 606 * a[4]
+ 942 * a[3]
+ 422 * a[2]
+ 789 * a[1] == 875498)
s.add( 766 * a[20]
+ 7 * a[19]
+ 283 * a[18]
+ 900 * a[17]
+ 211 * a[16]
+ 305 * a[15]
+ 343 * a[14]
+ 696 * a[13]
+ 590 * a[12]
+ 736 * a[11]
+ 817 * a[10]
+ 603 * a[9]
+ 414 * a[8]
+ 828 * a[7]
+ 114 * a[6]
+ 845 * a[5]
+ 175 * a[4]
+ 212 * a[3]
+ 898 * a[2]
+ 988 * a[1] == 714759)
s.add( 220 * a[20]
+ 30 * a[19]
+ 788 * a[18]
+ 106 * a[17]
+ 574 * a[16]
+ 501 * a[15]
+ 366 * a[14]
+ 952 * a[13]
+ 121 * a[12]
+ 996 * a[11]
+ 735 * a[10]
+ 689 * a[9]
+ 998 * a[8]
+ 689 * a[7]
+ 729 * a[6]
+ 886 * a[5]
+ 860 * a[4]
+ 70 * a[3]
+ 466 * a[2]
+ 961 * a[1] == 778853)
s.add( 313 * a[20]
+ 748 * a[19]
+ 522 * a[18]
+ 864 * a[17]
+ 156 * a[16]
+ 362 * a[15]
+ 283 * a[14]
+ 49 * a[13]
+ 316 * a[12]
+ 79 * a[11]
+ 136 * a[10]
+ 299 * a[9]
+ 271 * a[8]
+ 604 * a[7]
+ 907 * a[6]
+ 540 * a[5]
+ 141 * a[4]
+ 620 * a[3]
+ 701 * a[2]
+ 866 * a[1] == 584591)
s.add( 922 * a[20]
+ 399 * a[19]
+ 425 * a[18]
+ 26 * a[17]
+ 159 * a[16]
+ 224 * a[15]
+ 438 * a[14]
+ 770 * a[13]
+ 144 * a[12]
+ 406 * a[11]
+ 110 * a[10]
+ 991 * a[9]
+ 749 * a[8]
+ 701 * a[7]
+ 646 * a[6]
+ 147 * a[5]
+ 979 * a[4]
+ 674 * a[3]
+ 999 * a[2]
+ 913 * a[1] == 717586)
s.add( 13 * a[20]
+ 537 * a[19]
+ 225 * a[18]
+ 421 * a[17]
+ 153 * a[16]
+ 484 * a[15]
+ 654 * a[14]
+ 743 * a[13]
+ 779 * a[12]
+ 74 * a[11]
+ 325 * a[10]
+ 439 * a[9]
+ 797 * a[8]
+ 41 * a[7]
+ 784 * a[6]
+ 269 * a[5]
+ 454 * a[4]
+ 725 * a[2]
+ 164 * a[1] == 537823)
s.add( 591 * a[20]
+ 210 * a[19]
+ 874 * a[18]
+ 204 * a[17]
+ 485 * a[16]
+ 42 * a[15]
+ 433 * a[14]
+ 176 * a[13]
+ 436 * a[12]
+ 634 * a[11]
+ 82 * a[10]
+ 978 * a[9]
+ 818 * a[8]
+ 683 * a[7]
+ 404 * a[6]
+ 562 * a[5]
+ 41 * a[4]
+ 789 * a[3]
+ 200 * a[2]
+ 220 * a[1] == 587367)
s.add( 584 * a[20]
+ 597 * a[19]
+ 928 * a[18]
+ 532 * a[17]
+ 902 * a[16]
+ 858 * a[15]
+ 820 * a[14]
+ 240 * a[13]
+ 124 * a[12]
+ 899 * a[11]
+ 848 * a[10]
+ 822 * a[9]
+ 409 * a[8]
+ 491 * a[7]
+ 587 * a[6]
+ 715 * a[5]
+ 410 * a[4]
+ 268 * a[3]
+ 721 * a[2]
+ 915 * a[1] == 842245)
s.add( 421 * a[20]
+ 302 * a[19]
+ 327 * a[18]
+ 180 * a[17]
+ a[16] * 512
+ 160 * a[15]
+ 623 * a[14]
+ 28 * a[13]
+ 411 * a[12]
+ 53 * a[11]
+ 633 * a[10]
+ 560 * a[9]
+ 623 * a[8]
+ 477 * a[7]
+ 901 * a[6]
+ 287 * a[5]
+ 149 * a[4]
+ 726 * a[3]
+ 934 * a[2]
+ 875 * a[1] == 610801)
s.add( 838 * a[20]
+ 434 * a[19]
+ 792 * a[18]
+ 649 * a[17]
+ 462 * a[16]
+ 170 * a[15]
+ 980 * a[14]
+ 15 * a[13]
+ 295 * a[12]
+ 495 * a[11]
+ 666 * a[10]
+ 934 * a[9]
+ 17 * a[8]
+ 69 * a[7]
+ 367 * a[6]
+ 780 * a[5]
+ 291 * a[4]
+ 834 * a[3]
+ 587 * a[2]
+ 133 * a[1] == 653127)
s.add( 41 * a[20]
+ 422 * a[19]
+ 420 * a[18]
+ 224 * a[17]
+ 475 * a[16]
+ 854 * a[15]
+ 233 * a[14]
+ 179 * a[13]
+ 620 * a[12]
+ 69 * a[11]
+ 42 * a[10]
+ 684 * a[9]
+ 300 * a[8]
+ 745 * a[7]
+ 894 * a[6]
+ 554 * a[5]
+ 495 * a[4]
+ 66 * a[3]
+ 316 * a[2]
+ 391 * a[1] == 533470 )
if s.check() == sat:
ans = s.model()
for i in range(1,21):
print(chr(ans[a[i]].as_long()), end="")
#print(s.model())
#CDBBDCAAABBDBCCBCCAC
[Week2] 最简单的编码
动调一下,就能拿到变换后的table
CDABGHEFKLIJOPMNSTQRWXUVabYZefcdijghmnklqropuvstyzwx23016745+/89
然后这是魔改的base64
我是用cpp写的,网上搬的,改了几个偏移,不过年久已丢,此处用官方的
from regadgets import *
table = "CDABGHEFKLIJOPMNSTQRWXUVabYZefcdijghmnklqropuvstyzwx23016745+/89"
enc = "TqK1YUSaQryEMHaLMnWhYU+Fe0WPenqhRXahfkV6WE2fa3iRW197Za62eEaD"
index = []
number = [1,2,3,4]
for i in range(len(enc)):
tmp = table.index(enc[i]) - number[i % 4]
if tmp >= 0:
index.append(tmp)
else:
index.append(tmp + 64)
print(index)
for i in range(0,len(index),4):
sum = index[i] << 18 | index[i + 1] << 12 | index[i + 2] << 6 | index[i + 3]
for j in range(3):
print(chr((sum >> ((2 - j) * 8)) & 0xff), end="")
# [16, 38, 5, 51, 25, 20, 13, 20, 17, 39, 45, 2, 13, 3, 21, 5, 13, 35, 17, 31, 25, 20, 57, 3, 27, 52, 17, 9, 27, 35, 37, 31, 18, 19, 21, 31, 28, 36, 20, 52, 19, 4, 49, 25, 23, 51, 29, 15, 19, 53, 60, 53, 26, 22, 53, 48, 27, 4, 21, 61]
# BaseCTF{B45E64_eNCoDIn9_I5_rE4LLY_7OO_5implE}
[Week2] 喝杯下午茶
找key, 找enc,找delta就可以了。
from regadgets import *
k = [0] * 4
k[0] = 287454020
k[1] = 1432778632
k[2] = -1716864052
k[3] = -571539695
v = [0] * 10
v[0] = -1800277529
v[1] = 567661394
v[2] = 1380415805
v[3] = 67968151
v[4] = -210862220
v[5] = -1672218865
v[6] = 1793773528
v[7] = 1872692980
v[8] = -352477650
v[9] = 850810359
v = pack_dword(v)
r = b''
for i in v:
a, b = tea_decrypt(i, k, 1131796)
r += l2b(a)[::-1] + l2b(b)[::-1]
print(r)
# b'BaseCTF{h3r3_4_cuP_0f_734_f0R_y0U!!!!!!}'
[Week2] neuro爱数学
没做,搬一下官方的:
考点是简单的代码审计加代码逻辑仿写
点开IDA发现需要输入9个数
接下来简单分析逻辑
第一段进行了一个简单的运算操作
即计算: $$x_1*i^8+x_2*i^7+x_3*i^6+x_4*i^5+x_5*i^4+x_6*i^3+x_7*i^2+x_8*i^1+x_9*i^0$$
第二段计算(i-44)(i-58)(i-17)(i-6)(i-5)(i+4)(i+9)(i+37)
很多人看不懂,为什么不考虑一下本地模拟呢 or 动调
接下来事情显而易见 将第二段展开,得到的式子和第一段对比即可得到x1-x9
这里用python脚本完成,有能力的同学可以手算。
from sympy import symbols, expand
x = symbols('x')
polynomial = (x - 44) * (x - 58) * (x - 5) * (x + 37) * (x - 17) * (x + 9) * (x - 6) * (x + 4)
expanded_polynomial = expand(polynomial)
standard_form = expanded_polynomial.as_poly()
coefficients = standard_form.all_coeffs()
print(coefficients[::-1])
输入进程序即可得到flag
[Week3] UPX PRO
Linux 的加了upx,而且魔改了一些东西,我们放gdb里面
发现有反调试,我们考虑ptrace反调试catch syscall ptrace
然后s一下(过syscall),再运行
这样我们就能绕过ptrace反调试,然后
就可以绕过反调试,其实在反调试的地方已经过了,我们直接
得到coredump,然后拖入ida
显然我们已经得到了解压后的
随便翻一下,找到个base58,表是ABCDEFGHJKLMNPQRSTUVWXYZ123456789abcdefghijkmnopqrstuvwxyz
__int64 __fastcall sub_7FFFF7FF9518(__int64 a1, unsigned __int64 a2, __int64 a3, __int64 a4)
{
_BYTE v5[139]; // [rsp+20h] [rbp-A0h] BYREF
char v6; // [rsp+ABh] [rbp-15h]
int v7; // [rsp+ACh] [rbp-14h]
unsigned __int64 i; // [rsp+B0h] [rbp-10h]
int v9; // [rsp+B8h] [rbp-8h]
int v10; // [rsp+BCh] [rbp-4h]
sub_7FFFF7FF9362(v5, a3, a4);
v10 = 0;
v9 = 0;
v7 = 0;
for ( i = 0LL; i < a2; ++i )
{
v10 = (v10 + 1) % 128;
v9 = (v9 + (unsigned __int8)v5[v10]) % 128;
v6 = v5[v10];
v5[v10] = v5[v9];
v5[v9] = v6;
v7 = (v5[v10] + v5[v9]) & 0x7F;
*(_BYTE *)(a1 + i) ^= v5[v7];
}
return 0LL;
}
还有个魔改rc4
稍微还原一下
__int64 __fastcall rc4_init(char *s_box, char *a2, unsigned __int64 len)
{
char key_box[128]; // [rsp+18h] [rbp-90h] BYREF
char v5; // [rsp+9Fh] [rbp-9h]
int v6; // [rsp+A0h] [rbp-8h]
int i; // [rsp+A4h] [rbp-4h]
v6 = 0;
memset(key_box, 0, sizeof(key_box));
v5 = 0;
for ( i = 0; i <= 127; ++i )
{
s_box[i] = i;
key_box[i] = key_box[i % len];
}
for ( i = 0; i <= 127; ++i )
{
v6 = (key_box[i] + v6 + (unsigned __int8)s_box[i]) % 128;
v5 = s_box[i]; // swap
s_box[i] = s_box[v6];
s_box[v6] = v5;
}
return 0LL;
}
__int64 __fastcall rc4_crypt(char *a1, unsigned __int64 a2, char *key, unsigned __int64 key_len)
{
unsigned __int8 s[128]; // [rsp+20h] [rbp-A0h] BYREF
unsigned __int8 tmp; // [rsp+ABh] [rbp-15h]
int v7; // [rsp+ACh] [rbp-14h]
unsigned __int64 iter; // [rsp+B0h] [rbp-10h]
int j; // [rsp+B8h] [rbp-8h]
int i; // [rsp+BCh] [rbp-4h]
rc4_init((char *)s, key, key_len);
i = 0;
j = 0;
v7 = 0;
for ( iter = 0LL; iter < a2; ++iter )
{
i = (i + 1) % 128;
j = (j + s[i]) % 128;
tmp = s[i]; // swap
s[i] = s[j];
s[j] = tmp;
v7 = (s[i] + s[j]) & 0x7F;
a1[iter] ^= s[v7];
}
return 0LL;
}
我们发现key根本没用上,rc4的key_box全是0,是空的,可能是出题的时候的一个漏洞。
思路已经很明显了,就是把rc4的sbox空间改成128,就行了。
EXP
from regadgets import *
enc = [0x364A65466C271216, 0x2447243568082139, 0x29323C0F5A1A7D60, 0x4D647C3C45531544, 0x74152339130F7024]
enc = qword2byte(enc)
print(rc4_crypt(rc4_init(b'', 128), enc, 128))
# b'BaseCTF{Rc4_1$_@_G0od_3nCrypt!on_MethOd}'
[Week3] Dont-debug-me
ScyllaHide
[Week4] BaseRE
TLS Callback 和Main里面有花指令
Change base64 table to : HElRNYGmBOMWnbDvUCgcpu1QdPqJIS+iTry39KXse4jLh/x26Ff5Z7Vokt8wzAa0
b64decode('UXY5PpbpCshkP1CrPcU7DlZZSGd5WcO6qRB/D1dfbyZFP3ToncKKd5rXDGCA', my_table);BaseCTF{8edae458-4tf3-2ph2-9f26-1f8719ec8f8d}