跳转至

2023 12月第4周周报

一、完成事项⚓︎

  • 64位手动脱壳!
  • 使用CFF Explorer组织系统ASLR重定位
  • 尝试gdb调试,ida远程调试
  • 学习特征值主要算法TEA,DRS,MD5

二、未完成事项⚓︎

  • 强网杯babyre没搞出来

三、下周待做事项⚓︎

  • 元旦水友赛

四、本周学习的知识⚓︎

一、读师傅们周报的启发⚓︎

  • Fi1ix: AES和SM4,大小端序的问题,迷宫脚本
  • lyp: ida伪代码里的字符串是小端序,shift+E提取地图数据
  • lo1see:gmbh和flag的ASCII码值差1

二、UPX手动脱壳(64位)⚓︎

示例为 [SWPUCTF 2022 新生赛]upx 中的附件(64位,UPX3.96壳),可以用工具脱壳。下面尝试手动脱壳。
XP后的系统都有ASLR(地址空间随机化),导致dump后程序运行出错,因此我们首先用CFF Explorer修改该文件的Nt Header,禁用ASLRimage.png在Nt Header下的Optional Header里修改Characteristics,勾选Relocation info srtipped from file。关闭后记得保存。
用x64dbg打开文件,进入系统断点(push rbx)。image.png
image.png
按F9到达该断点(这里要按两次,上面还有个别的什么断点)
F7走完push压栈部分image.png
观察到RSP的变化,在其上右键“在内存窗口中转到”
image.png
在右下角该地址右键,设置硬件断点
image.png
F9运行到断点处,看到下面的jmp大跳应该是入口,设置断点,F9跳过去
image.png
F7步入程序
image.png
aaa56cef3929b32cc82624303473f0a1.png
往下翻可以看到提示字符串
这就正式进入了原程序,可以进行dump了
image.png
先点“IAT Autosearch”,再点“Get Imports”,在“Imports”中删除掉带有红色叉叉的,再点击“Dump”,之后“Fix Dump”选中之前的Dump文件,修复成功。
image.png
image.png
image.png
p04 副本_dump_SCY.exe 也可以正常运行
拖入IDA中,这里会不报错,Yes不用管它
image.png
image.png
(由于某种神秘力量?)没有main函数,只能通过字符串来找函数
image.png
image.png
X键找一下位置
image.png
可以看到大致的代码
如果想把字符串展开看,可以(退到IDA View-A中)修改Segment,取消w勾选
image.png
image.png
修复后
image.png
显然sub_140001540是printf函数,脱壳结束

三、GDB调试(pwndbg)⚓︎

  1. 打开文件:gdb ./2-simpleCrackme

    Text Only
    1
                   `gdb --args ./ping -c 10 127.0.0.1`<br />                         file命令
    
  2. 调试快捷键

  3. r:启动
  4. c:继续
  5. si:单步步入
  6. ni:单步步过
  7. finish:执行到当前函数返回
  8. b:断点
  9. intfo b(或l):列出所有断点
  10. del 序号:删除断点
  11. clear:删除指定位置断点(clear *main)
  12. 示例:image.png

image.png

四、IDA远程调试⚓︎

  1. 选择调试器image.png
  2. 在虚拟机里查看域名,之后要用image.png
  3. 填写IDA

image.png

  1. 虚拟机启动 ./linux_server64(视位数而定)

image.png

  1. 可以启动调试了image.png

image.png

五、特征值算法⚓︎

TEA⚓︎

例题:babyre(unsolved)
运行内容:
image.png
64位无壳
image.png
符号表被藏了,只能通过字符串寻找主函数
image.png
从字符串长度判断切入主函数
image.png
20行应当是输入部分
24行 sub_140011019 应当是存储Str到一个数组
进26行 sub_14001106E 看一下:
image.png
转换为16进制:v3 = 0x90508D47; v3 -= 0x77BF7F99;
应该是TEA加密,倒推得到解密脚本中的 delta=0x90508D47-3340x77BF7F99=
image.png
byte_14001E000为密钥:49, 183, 182, 49
27行 sub_140011087 :
image.png
是一个拆字节的函数(对于从 a1 中读取的每个32位整数,使用一个内层循环将其拆分为四个字节)
最终存储到image.pngbyte_14001E218数组内
查一下byte_14001E040应该是密文:image.png
224, 243, 33, 150, 151, 199, 222, 137, 155, 202, 98, 141, 176, 93, 252, 210, 137, 85, 28, 66, 80

六、ISCTF刷题⚓︎

crackme⚓︎

有upx壳,但是工具脱壳失败,直接手脱即可
image.png
image.png
更简单的方法是拖进cmd可以直接运行!??
image.png

EasyRe(疑似错题)⚓︎

64位无壳直接进
image.png
可以看出 ]P_ISRF^PCY[I_YWERYC 是最终的密文(20位)
第一个循环:进行逐位异或
第二个循环:将字符串中的B和X换掉,但是IDA默认编译出来的-101-66显然是负数,本不应该输出任何字符,但是在C中却可以运行,分别换成了Y和C
04a895d7d01f4a57ac297c45f55b1db9.png
苦思冥想后我发现,256-101-155,155-66=89正好对应Y,电脑自动把-101转换成155进行计算,因为出现了整数溢出,完整的0-256表从后往前溢出,才造成了这样的结果
选中“-101”(一定要包括负号),先转化为16进制,再换成十进制,就会变成155~~(IDA榆木脑袋!)~~
image.png
第三个循环:看似是一个字符串逆序,实际上是将前半部分字符串对称到后半部分去,损失了一般的数据。这里好像是编错了,如果真是这样就没法解密。
如果当成是逆序,可以写出解密脚本:
image.png
image.png
出现了正常的flag,应该是题目出错了。

babyre⚓︎

pyinstaller打包,用pyinstxtractor.py和在线pyc转py可以得到python源代码:
(pyc魔术头没被抹去,可以直接用babyre.pyc进行转码)

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import libnum
from Crypto.Util.number import *
flag = 'ISCTF{******************}'
flags = flag.encode()
e = 65537                                     #rsa加密
p = libnum.generate_prime(1024)               #生成两个大素数
q = libnum.generate_prime(1024)
n = p * q
m = bytes_to_long(flags)
c = pow(m, e, n)       #m的e次方对n取模      m^e%n=c  m^e=k*n+c
output = open('output.txt', 'w')
output.write('p+q =' + str(p + q) + '\n')
output.write('(p+1)*(q+1)=' + str((p + 1) * (q + 1)) + '\n')
output.write('c=' + str(c) + '\n')
output.close()
可以看到是一个魔改的rsa
解密脚本如下:
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#babyre wp
from z3 import *
import libnum
from Crypto.Util.number import *
p,q,c=Ints('p q c')
S = Solver()
S.add(p+q==292884018782106151080211087047278002613718113661882871562870811030932129300110050822187903340426820507419488984883216665816506575312384940488196435920320779296487709207011656728480651848786849994095965852212548311864730225380390740637527033103610408592664948012814290769567441038868614508362013860087396409860)
S.add((p+1)*(q+1)==
21292789073160227295768319780997976991300923684414991432030077313041762314144710093780468352616448047534339208324518089727210764843655182515955359309813600286949887218916518346391288151954579692912105787780604137276300957046899460796651855983154616583709095921532639371311099659697834887064510351319531902433355833604752638757132129136704458119767279776712516825379722837005380965686817229771252693736534397063201880826010273930761767650438638395019411119979149337260776965247144705915951674697425506236801595477159432369862377378306461809669885764689526096087635635247658396780671976617716801660025870405374520076160
)
S.check()
d = S.model()
p = d[p].as_long()
q = d[q].as_long()
e=65537
c=5203005542361323780340103662023144468501161788183930759975924790394097999367062944602228590598053194005601497154183700604614648980958953643596732510635460233363517206803267054976506058495592964781868943617992245808463957957161100800155936109928340808755112091651619258385206684038063600864669934451439637410568700470057362554045334836098013308228518175901113235436257998397401389511926288739759268080251377782356779624616546966237213737535252748926042086203600860251557074440685879354169866206490962331203234019516485700964227924668452181975961352914304357731769081382406940750260817547299552705287482926593175925396
phi = (p-1)*(q-1)
n=p*q
m = pow(c,inverse(e,phi),n)      
flags=long_to_bytes(m)
flag=flags.decode('utf-8','ignore')
print(flag)
先用Z3强行求出p、q,算出常规rsa中的phi,然后套用公式求出m
注意各类型的转换

easy_z3⚓︎

明显z3方程求解,求出l再连在一起

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
print("Please input flag:")
flag = input()
if len(flag)!=42:
    print("Check your length!")
    exit()

l=[]
for i in range(6):
    s=""
    for j in flag[i*7:i*7+7]:
        s+=hex(ord(j))[2:]
    l.append(int(s,16))
if (
(593*l[5] + 997*l[0] + 811*l[1] + 258*l[2] + 829*l[3] + 532*l[4])== 0x54eb02012bed42c08 and \
(605*l[4] + 686*l[5] + 328*l[0] + 602*l[1] + 695*l[2] + 576*l[3])== 0x4f039a9f601affc3a and \
(373*l[3] + 512*l[4] + 449*l[5] + 756*l[0] + 448*l[1] + 580*l[2])== 0x442b62c4ad653e7d9 and \
(560*l[2] + 635*l[3] + 422*l[4] + 971*l[5] + 855*l[0] + 597*l[1])== 0x588aabb6a4cb26838 and \
(717*l[1] + 507*l[2] + 388*l[3] + 925*l[4] + 324*l[5] + 524*l[0])== 0x48f8e42ac70c9af91 and \
(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x4656c19578a6b1170):
    print("Good job!")
else:
    print("Wrong\nTry again!!!")
    exit()
解密:
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from z3 import *
from Crypto.Util.number import *
l = [Int(f'l_{i}') for i in range(6)]   #注意定义字符串数组的语法

S = Solver()  #创建约束求解器

S.add((593*l[5] + 997*l[0] + 811*l[1] + 258*l[2] + 829*l[3] + 532*l[4])== 0x54eb02012bed42c08)  #添加约束条件
S.add((605*l[4] + 686*l[5] + 328*l[0] + 602*l[1] + 695*l[2] + 576*l[3])== 0x4f039a9f601affc3a)
S.add((373*l[3] + 512*l[4] + 449*l[5] + 756*l[0] + 448*l[1] + 580*l[2])== 0x442b62c4ad653e7d9)
S.add((560*l[2] + 635*l[3] + 422*l[4] + 971*l[5] + 855*l[0] + 597*l[1])== 0x588aabb6a4cb26838)
S.add((717*l[1] + 507*l[2] + 388*l[3] + 925*l[4] + 324*l[5] + 524*l[0])== 0x48f8e42ac70c9af91)
S.add((312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x4656c19578a6b1170)

S.check()  #检测是否有解

d=S.model()  #输出

flag = b''  #字节字符串
for i in range(6):
    flag += long_to_bytes(d[l[i]].as_long())   #long转bytes拼接
print(flag)

⚓︎

五、本周自己学习过程中遇到的问题和疑问点⚓︎

(1)z3好像炸不了指数方程
(2)反调试函数具体怎么找
(3)
(4)

六、情感、思考、观点⚓︎

  • 参加了安洵杯,但是水平还太低。。。啥也不会。积累经验努力学习吧

七、在团队的感触和建议⚓︎