首页
论坛
课程
招聘
[原创]2020KCTF
2020-4-14 10:50 3784

[原创]2020KCTF

2020-4-14 10:50
3784

KCTF从入门到实战(九)- 杯弓蛇影

简介

大家好! 我们又见面了! 继《传家之宝》和《南充茶坊》之后,这一次我们奉上实战系列作品——《杯弓蛇影》

 

故事背景简介

春夏秋冬,寒来暑往,日复一日,这人间循环往复空换时光流逝,似乎少了点乐趣。

无所事事便没有好事。

不知从哪儿传出的“巳蛇将出”的谣言,传说巳蛇亦蛇亦弓,入水为蛇,踪迹全无,出水为弓,毙敌百步。竟也有人捕风捉影、信以为真,一传十,十传百,事实变得更加扑朔迷离,人心惶惶。

遂智者言,地势坤、风入松、松如浪,一景一画皆有其意,善用者,良马也。

脱壳

使用的反调试:异常,硬件断点检测,内存检验,NtQueryInformationProcess,简单的反dump等。这些反调试有的会造成导入表加密,有的会使代码段错乱,造成异常,有的会修改算法,需要找出所有的并且绕过这些反调试。

内存校验数据选择放在了 紧跟在DOS头后得无效数据

清楚掉所有的反调试后

导入表保护:清除了源程序的导入表,使用了iat混淆,你需要修复导入表

 

VM识别解析

模拟存储识别:

1. 代码空间

Code用于模拟在一开始new出来

1. 代码标识 CD        8字节

2.代码sizeof            8字节

2.代码大小              8字节

进行拷贝赋值

2. 环境寄存器[9]

unsigned long long ER[9];//9个计算机环境寄存器 初始化的事后使用

#define  TE 0       //Text End

#define  HS 1       //Heap Start

#define  HE 2       //Heap End

#define  SS    3       //Stack Start

#define  TOP 4       //Stack End

//3个指针寄存器

#define  IP 5       //指令指针                (指令运行后必然使用 ER[5])

#define  SP 6       //栈指针

#define  FP 7       //过程调用帧栈指针

...

 

3.  寄存器[10];

类型 unsigned long long

寄存器[1] - 寄存器[9]

GR[1]      -  GR[9]

指令解析:

ps:(有些操作会随着SetProperty属性更改而进行修改)

指令操作
[默认编号0]:LEA(取地址)
[默认编号1]:SetProperty  寄存器,属性值(立即数)()更改不同属性的值
[默认编号2]:SetProperty  寄存器,属性值(立即数)()更改不同属性的值
[默认编号3]:LOADDI
[默认编号4]:LOADQI
[默认编号5]:LOADF4I
[默认编号6]:LOADF8I
[默认编号7]:LOADB
[默认编号8]:LOADW
[默认编号9]:LOADD              [寄存器],[内存]
[默认编号10]:LOADQ
[默认编号11]:取地址
[默认编号12]:-
[默认编号13]:STOREBI
[默认编号14]:STOREWI
[默认编号15]:STOREDI[寄存器],立即数 
[默认编号16]:STOREQI
[默认编号17]:STOREF4I
[默认编号18]:STOREF8I
[默认编号19]:STORERB                          [内存][内存] SetProperty 属性为准
[默认编号20]:STORERW
[默认编号21]:STORERD
[默认编号22]:STORERQ
[默认编号23]:-待扩展
[默认编号24]:-待扩展
[默认编号25]:MOVB                              [内存][内存]   
[默认编号26]:MOVW
[默认编号27]:MOVD
[默认编号28]:MOVQ
[默认编号29]:-待扩展
[默认编号30]:-待扩展
[默认编号31]:MOVRR                              [寄存器][寄存器] 
[默认编号32]:MOVRF4
[默认编号33]:MOVRF8


[默认编号34]:PUSHFP
[默认编号35]:PUSHB
[默认编号36]:PUSHW
[默认编号37]:PUSHD
[默认编号38]:PUSHQ
[默认编号39]:PUSHF4
[默认编号40]:PUSHF8
[默认编号41]:POPFP
[默认编号42]:POPB
[默认编号43]:POPW
[默认编号44]:POPD
[默认编号45]:POPQ
[默认编号46]:待扩展
[默认编号47]:待扩展
[默认编号48]:INCR
[默认编号49]:DECR
[默认编号50]:ADDR
[默认编号51]:SUBR
[默认编号52]:MULR
[默认编号53]:DIVR
[默认编号54]:--
[默认编号55]:--
[默认编号56]:--
[默认编号57]:--
[默认编号58]:--
[默认编号59]:--
[默认编号60]:--
[默认编号61]:--
[默认编号62]:AND
[默认编号63]:OR
[默认编号64]:XOR
[默认编号65]:NOT
[默认编号66]:SHRA
[默认编号67]:SHRL
[默认编号68]:SHL
[默认编号69]:CALL
[默认编号70]:RET
[默认编号71]:MOVSF
[默认编号72]:LDFPOB
[默认编号73]:LDFPOW
[默认编号74]:LDFPOD
[默认编号75]:LDFPOQ
[默认编号76]:JMPI
[默认编号77]:JNZ
[默认编号78]:JNS
[默认编号79]:JNL
[默认编号80]:JZ
[默认编号81]:JS
[默认编号82]:JL
[默认编号83]:COMP
[默认编号84]:COMPI
[默认编号85]:OUTO
[默认编号86]:OUTD
[默认编号87]:OUTH
[默认编号88]:OUTC
[默认编号89]:--
[默认编号90]:--
[默认编号91]:NOP

例子strlen:

LEA       R1,HELLO
MOVRR     R3,R1
L1:
	LOADB 	R2,R1
	JZ      END
	INCR    R1
	JMPI    L1
END: 
	SUBR    R1,R3 
	OUTD    R1
	HALT
	; 字符串 AA AA AA 00
HELLO: DB AA AA AA 00

二进制解析CODE

unsigned AnsiChar data[70] = {
//标识符
	0x43, 0x44, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,  
//code 大小                  
   0x2A, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,  
//data 数据大小                    
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    
//lea 寄存器[1],地址                
   0x00, 0x01, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 
//MOVRR 寄存器3,寄存器1      
   0x1F, 0x03, 0x01,     
//loadb 寄存器2,寄存器1                                                          
   0x07, 0x02, 0x01,    
//jz  地址                                                           
   0x50, 0x24, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,  
//INCR              
   0x30, 0x01,   
//jmp跳转                                                                                                
   0x4C, 0x0D,                                                                       
   [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,] 
//SUBR 寄存器1,寄存器3
   0x33, 0x01, 0x03,  
//OUTD                                                              
   0x56,0x01,          
//结束符                                                                
   0x5C,  
//数据字符串                                                                               
   0xAA, 0xAA, 0xAA, 0x00
};

指令混淆识别:

1.非混淆代码会 与外界交互

2.前面会执行多个pushd 指令 popd指令结束

 

算法破解

此题使用了一种面向多明文的数据对称加密算法

该算法能够对同一个密文,使用相同的计算过程,在不同的密钥作用下,得出既定的不同明文。

该算法能够为“必须在不同环境下表现出不同功能的程序设计”提供一种安全的实现方案。只有拥有合适密钥才能解出理想代码,否则不仅看不到理想代码,甚至不能确定所谓的理想代码是否真的存在。

 

为了符合参赛出题要求,我们将‘一批密钥’和‘每个密钥应该解出什么样的明文’固定在了CrackMe里面(我们认为,就算公开了),还将解密算法固定在了CrackMe里面(我们认为也算公开了),然后要求攻击者给出正确的密文,即:序列号(实际上是在挑战攻击者找出正确的加密算法)

密码算法描述

 

假设给定一组密钥masterkey[i]和一组对应的明文m[i]

 

明文预处理

 

0x01

       对输入的n个明文m[i](i=1,2,...,n)均填充到等长长度且为L的倍数,令结果为m_p[i](L为分组密码中分组的长度,本题L为32bit)

       即:填充到长度为ceil(maxlen(m[1],m[2],…,m[n])/L)*L;其中ceil()函数返回不小于给定数字的最小整数

 

0x02

       对填充后的m_p[i]分别采用Hash算法(本题选用的是SHA-256),分别得到m_h[i];

 

0x03

       m_p[i]分别循环地与m_h[i]异或,生成m_hp[i];

 

0x04

       将m_hp[i]分别与m_h[i]拼接,得到m_hpd[i];

 

0x05

       将m_hpd[i]分别以Lbit为分组长度进行分组(此题L为32bit)

       m_hpd[i]=m_hpd[i][0] || m_hpd[i][1] || ... || m_hpd[i][length/L] (length为每个明文m_hpd[i]的长度)

 

密钥预处理

 

0x01

       随机生成salt(每个salt的长度为Lbit)

 

0x02

       将n个salt分别连接在n个密钥口令masterkey[i]后面得到k[i]

 

0x03

       对k[i]进行Hash生成key[i](此题选用的是SHA-256)

 

0x04

       对key[i]分别以Lbit为分组长度进行分组(此题L为32bit)

       key[i]=key[i][0] || key[i][1] || ... || key[i][length/L] (length为每个分组key[i]的长度)

 

0x05

       对分组后的不同的key[i]对应的相同位置的分组检查是否有相等,若有,则重复12345步

 

加密

 

0x01

       随机产生多个长度为Lbit的数据offset(此题L为32bit)

 

0x02

       生成密文的函数为:

       c=Enc(key[1],...key[n],m_hpd[1],...mhpd[n])

        =(R_11 || R_21 || ... || R_n1 || offset[1]) || (R_12 || R_22 || ... || R_n2 || offset[2])...(R_1m || R_2m || ... || R_nm || offset[m])

       其中m为明文的分组组数

              R为加密得到的密文数据块

              n为输入的明文和密钥个数

              offset为加密时生成的随机数

 

0x03

       在每一个分组中:

       在第i个分组:

       c_i=Enc(key[1][i%t],key[2][i%t],...,key[n][i%t],m_hpd[1][i],m_hpd[2][i],...,m_hpd[n][i])

          =R_1i || R_2i || ... || R_ni || offset[i]

       

       其中n为输入的明文和密钥个数

              t为密钥的分组组数

 

      对n个坐标(key[1][i%t],m_hpd[1][i]^offset[i])

                      (key[2][i%t],m_hpd[2][i]^offset[i])

                                   ....

                      (key[n][i%t],m_hpd[n][i]^offset[i])

 

 

      采用拉格朗日插值定理所生成的系数为R_1i,R_2i,...,R_ni

      offset[i]为随机数,以确保坐标的第2个值都小于p

      (其中所有的运算均为模p运算,p为小于2^L的最大素数)

     

0x04

       对所有分组加密完成,产生的所有系数以及offset组成最终的密文

 

解密

0x01

       对给定的n个密钥用加密时同样的方法对密钥进行预处理并分组

       得到key[i]=key[i][0] || key[i][1] || ... || key[i][length/L](i=1,2,...,n)

 

0x02

设k为key[i]

       解密函数为:m=Dec(k,c);

       其中,第j个分组明文的解密方法为:

                           m[i]=Dec(k[j],c[j])

                               =Dec(k[j],R_1j,R_2j, ...,R_nj,offset[j])

                               =(R_1j*k[j]^n-1+R_2j*k[j]^n-2+...+R_nj)^offset[j]

       其中,R_1j,R_2j,...,R_nj分别为第j分组的密文数据块,key[j]中的j需要对t取模, t为密钥的分组组数

       *,+均为模p运算,p的取值与加密时相同

        

       对所有分组进行解密后,将解密得到的明文分组拼接在一起得到完整的明文

 

0x04

       对拼接在一起的明文进行分离,得到m_hp[i]与m_h[i]

 

0x05

       将m_hp[i]循环与m_h[i]进行异或得到m_p[i]

 

0x06

       将m_p[i]进行Hash运算(SHA256)得到的结果与m_hp[i]进行比较验证

       如相等则表示第i个明文解密成功,如不相等则表示解密失败

 

0x07

       以上步骤重复n次,便可成功解密得到所有的n对明文

       

出题

      此题用Username作为种子,利用KDF函数(实际上是SHA-256的变种)生成salt和offset分别用于上述算法所需的对密钥进行预处理和加密过程。

      对我们选取的3对明文和密钥利用以上方法进行加密(即n=3,L=32bit)

      加密算法产生的系数(即以上算法产生的密文去掉offset)便为序列号

     

crackme运行过程 

      CM.EXE会对用户输入的Username作为种子,利用KDF函数生成salt和offset分别用于上述算法所需的对密钥进行预处理和解密过程。

      对输入的序列号作为密文,用正确的3对密钥对密文进行解密,若能在上述算法中验证解密成功且解密得到的明文和我们公开的明文一致,则序列号正确。


 PS.由于本人疏忽 在第一次出题时只按照上述算法的解密中的步骤0x06判断hash值是否相等验证序列号是否正确,遗漏了将解密得到的明文和公开的明文对比是否一致的判断,因此出现了bug,中途修改了题目 望各位大佬见谅!


用于加密产生密文的三对明文和密钥公开如下:(英文逗号为分割符,逗号前为密钥,逗号后为明文)

这杀软好多呀,好像是个VM,我是个任务管理器

这机器里文件修改时间分布广,找包含关键词的文件

伊娃找到了理想植物,赶紧带回去给船长


《0day安全 软件漏洞分析技术(第二版)》第三次再版印刷预售开始!

最后于 2020-4-28 00:50 被xh1998编辑 ,原因:
上传的附件:
收藏
点赞0
打赏
分享
最新回复 (3)
雪    币: 429
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:34 )
在线值:
发帖
回帖
粉丝
xh1998 活跃值 2020-4-28 01:15
2
0

因为发现bug所以申请换题。新版与旧版保护方法不变,序列号答案不变。

上传的附件:
雪    币: 537
活跃值: 活跃值 (1557)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2020-4-28 02:36
3
0
xh1998 因为发现bug所以申请换题。新版与旧版保护方法不变,序列号答案不变。
已更新并群通知大家了。
雪    币: 19
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_tfcmlgee 活跃值 2020-5-6 06:08
4
0
mark
游客
登录 | 注册 方可回帖
返回