TC5.0 (一个脚本开发工具)其底层实现原理分析与推测(半成品)

发送此贴的原因也算是回馈论坛了,毕竟自己一直潜水学习了很多大大(来至于不同地方)的知识。作为一个新手,很感激各位大佬的知识。

起因

由于某些原因,在周五第一次接触到了这样一个脚本,而这个脚本的逆向,有些棘手。其运行行为特征也非常奇怪,和之前的纯c&c++加上壳子完全不一样,首先肯定是vc++的一个程序其中混杂了相关的加密内容。
PE工具分析出来如下图(类似,这个test_en是我写的生成的):

  (有混淆就混淆吧,挡不住f7大法)
然后long long time 的查找资料,终于在网络上发现了这个脚本的一些有意义的特征。
这个脚本是用TC工具生成的,我第一次听说TC这个工具,和他类似的按键精灵和易语言我都听过。
是我孤陋寡闻了,也印证了学习的必要性。接下来就是查找安装这个TC工具(为啥要下5.0,因为5.0是我在官网找到的最老的版本了,越老越容易暴露特征),安装后自己创建一个工程如下图(对我来说使用他贼简单,已有其他语言编程基础):(本文文末提供所有本文工具下载)

这里我发现了一个有意思的地方,tc作者实现的这套语言集成化极高,但是扩展性等于0,这样有个好处就是实现的原理会简单一些吧,我猜的。
可能有人会问:为啥我要去找这个开发工具写一个test程序,因为我想吐槽一下这个tc的官方论坛贼差劲,tc的逆向资料等于空白,我不知道是不是有人有但是不分享吧。我作为一个小白,我想要 逆向掉这样一个脚本,我必须要了解其生成的程序的原理,包含运行原理和他这门语言的实现原理。(说实话,可能是我太自信了,但是没办法啊,逆向资料太少了)。
还有这里我在想吐槽一句:tc这个我感觉网上很多人的资料都是用来做脚本,从来没有人介绍一下这个工具的底层运行原理。并且官方都没有任何资料解释其原理的,都是卖脚本的,感觉有种闭门造车的感觉,一个语言要发展,社区一定要活跃,否则就呵呵。
到这里,其实我周五想逆向的脚本已经被我抛开了,我只想知道tc这套框架的实现底层原理,我觉得挺有意思的,关键网上资料还少,挺有挑战性。
说不定我掌握这样的原理,我也能实现一个自己的语言出来,不一定要全,一定要专,这样我写的程序给别人逆向的话,可以挡住80%的逆向人员(靠工具自动化的),就像我这样的小白,还有20%的人能手动分析的,只要有功夫,什么都能分析的,拦不住的。(我感觉我已经十分的膨胀了,想自己创造一种语言出来。{:301_997:} {:301_997:} {:301_997:} )(关于上文怎么分析出来脚本是tc写的,请听我慢慢道来)

正文

在我之前学习win的逆向的时候,就是字节写一个简单的win32弹框程序进行分析,直接拉入od,分析起来,很舒服,因为跟明文差不多(:lol 因为没有加壳)
同样,这里我把我写的test_en.exe拉入od,运行,分析。

tc程序特征锁定

拉入od,点击确定按钮,弹了一个框出来,暂停,看调用堆栈,不用怀疑,出现了两个明显的特征dll,TLib.dll和TApi.dll。为什么我说它是特征dll,我们可以在tc5的安装目录发现这两个dll,我也在周五的脚本发现了这两个dll,由此可以猜测,这个程序是tc写的。(其实理由有点牵强,但是我可以继续往下分析验证我的观点)

查看程序运行的依赖:

这里我还有一条证据:
在tc开发工具的安装目录的tlib和test_en释放的tlib做md5验证,一样的文件。

tc程序运行行为特征分析(目标就是想让我写的程序点击开始按钮后,执行messagebox("!!!!!========"))

通过观察周五的脚本和我写的test_en.exe的开始运行过程中,在OD里面我发现了其会释放TApi和TLib这两个库到用户程序临时目录(因为我发布的test_en.exe不包含任何exe,说明这两个dll是打包到可执行文件中了的)。
根据我写的tc脚本程序。
[mw_shl_code=cpp,true]//开始按钮_点击操作
function start_click()
var btn_start_content = "点击开始TEST"
var btn_start_title_msg = "提示"
messagebox(btn_start_content, btn_start_title_msg)

var btn_test1="AAAAAAAAAAA"

if(0 == strcmp(btn_start_content, btn_start_title_msg))
    var btn_test2="BBBBBBBBBBB"
    messagebox("========")
else
    var btn_test3="CCCCCCCCCCC"
    messagebox("!!!!!========")
end

end

//退出按钮_点击操作
function exit_click()

var btn_exit_content = "点击退出AAAAA"
var btn_exit_title_msg = "提示"
messagebox(btn_exit_content, btn_exit_title_msg)

end

function test_en_init()
//这里添加你要执行的代码

var content = "call init"
var title_msg = "提示"
messagebox(content, title_msg)

end

function test_en_destroy()
//这里添加你要执行的代码
var content = "call detroy"
var title_msg = "提示"
messagebox(content, title_msg)
end

//点击关闭_执行操作
function test_en_close()

var content = "call close"
var title_msg = "提示"
messagebox(content, title_msg)
exit()

end

//消息路由功能
function test_en_pretranslatemessage(hwnd,message,wParam,lParam,time,x,y)

var test = "pretranslatemessage"
return false

end

//消息过程功能
function test_en_windowproc(message,wParam,lParam)
var test = "windowproc"
end

[/mw_shl_code]

其会在窗口初始化销毁以及鼠标点击事件情况下,执行我用“tc写的程序”,上文弹框的图和下面程序运行初始化的图暴露了一个事情。

到此我可以猜测,tlib和tapi是为了"解释执行"我写的函数,而我写的函数是什么时候调用的呢?是对应的控件事件的时候。其实tc开发工具就暗示我了,只是我没有get到点。

是不是我猜想的那样呢?我们还得深入汇编分析。
首先是关于tc生成的程序执行的原理,在上图按钮点击后,暂停,然后一直运行到主程序空间,你会发现你定义的很多tc调用都会进入以下的fun3。
首先我唯一可以确定的是,从主程序传给tlib只有一个参数,是对应事件的我们在tc中定义的函数名。

我们首先去IDA里面看看fun3的定义,

可以看到就是把func_name和GlobalRunTime::g_RunManager这两个参数传给了tlib,然后执行我们在tc中定义的func_name。
剩下就只有两个问题要解决,解决后tc生成的程序底层执行原理就在我们的眼皮子底下了:
1 程序是怎么调用的fun3这个方法,什么原理(新手难度)?
2 fun3是怎么解释执行我们在tc中定义的函数(最难的)?  

关于第一个问题,我想我可以解答,我在调试的过程中,在button下消息断点后,单步执行到主程序空间,你会发现,这个线程会在一个特定地方执行。

根据已知的常识知识,我们在win32自定义界面程序开发的时候,会这样做:
RegisterClassW注册一个窗体进入系统,否则你不能够[color=rgb(0, 0, 0)][backcolor=rgb(254, 254, 242)][font=Verdana, Arial, Helvetica, sans-serif][size=13px]CreateWindow,在[/size][/font][/backcolor][/color]RegisterClassW的参数是一个WINDCLASS指针,而这个WINDCLASS其中一个成员变量[color=rgb(79, 79, 79)][font=&quot]lpfnWndProc[/font][/color][color=#4f4f4f][backcolor=rgb(246, 248, 250)][font=&quot] [/font][/backcolor][/color]指向了一个回调函数,这个回调函数专门用于处理os发送到这个窗口的消息,你可以在这里面处理自己感兴趣的消息,不处理的丢给[color=#333333][font=arial, 宋体, sans-serif]DefWindowProc处理。[/font][/color]
[color=#333333][font=arial, 宋体, sans-serif]
[/font][/color]
[color=#333333][font=arial, 宋体, sans-serif]回到正题,那么我可以猜测tc调用fun3的原理是,在窗口消息回到函数中,根据特定的消息,调用tlib,只需要传入一个特定消息对应的tc中定义的函数名即可,还有这个[/font][/color]GlobalRunTime::g_RunManager全局变量也是重点,圈起来,要考。也就是说,tc这门语言实现起来的原理就是:我在tc中定义的和事件相关的函数,根据os事件驱动来调用,然后传入对应时间对应的tc定义的函数名即可实现过程调用。

关于第二点,tlib是怎么解释执行我们定义的函数的,我没有分析完,昨天陷入误区了,也非常难,可能我还需要其他帮助或者更多的信息来分析,所以本文算是一个半成品,因为最最最核心的内容我都没有分析出来。
以下是我分析了的部分资料:
1 一个事件对应的tc中的方法,会在一次TRunManager::execute调用中执行完,也就是说,调用一次类似fun3的,就会完整的执行完一个tc中定义的事件对应函数。
2 在TRunManager::execute中,会根据TRunManager::findFuncBlockByName(GlobalRunTime::g_RunManager, func_name)来处理一个叫做struct BaseBlock的结构体,我有理由怀疑,这个结构体解码成功,tc的框架的运行原理解释就完成了。

3 根据上图,处理好struct BaseBlock结构体后,又会调用我上图已经改了名字的函数:parse_code_and_run,这里还有一个重要的知识点,划重点,要考,这个parse_code_and_run进去后,会执行完事件对应的我们在tc中定义的函数。
下面是ida中parse_code_and_run的相关已知的注释

4 初始化好后,调用tapi执行对应的action。

总结

1 很遗憾,由于自己技术有限,昨天只能够分析出那么多了,但是我现在已经卡在了分析解释执行的部分上,昨晚觉都没有睡好。
2 从tc这门语言技术实现的角度来说,我还是可以学习到如下的知识点,自己可以建立一个模板程序,然后在程序的对应位置通过一定手段插入我自己定义的方法。一定手段可以是我定义的一个插入工具,我自己定义的方法可以抽象为我自己的一门语言。站着别人的肩膀上,可以用最小的代价,做出一个有趣的事情。
3 从上面来看,其实我想逆向那个周五的脚本已近跑偏了,我跟多的是想探寻类似tc,易语言,按键精灵这种框架实现的底层原理,很有趣。
4 这是我第一次接触tc、按键精灵、易语言之类的,原来国人已经做了很多工作了,抽象了很多内容,至少对于没有学过c||c++的人来说,开发一个小工具是个简单的事情,让许多许多的人都有机会实现一个自己的软件。这里还是对这些作者表示敬意,要实现这些内容,必须对计算机底层,或者说win的运行原理有深入的分析才行。

5 tc分析只能暂时到这里,缺了很多资料,感觉是在摸黑盒。如果有大佬能够指点指点,完成本文的分析,我在此感激不尽,文末提供我写的程序和tc5的安装包,如果大佬,可以来本文指点指点,让我学习学习。

免责声明

这篇文章,都是我自己的感悟,如果不对谁的胃口,请勿喷谢谢。
如果本文侵犯了谁的权利,请联系我删除,谢谢。
本文提供的附件请自行放到虚拟机里面测试,这样更加安全。

吐槽

tc的官网论坛真的难受,资料是真的少,官网论坛,一点技术氛围都没得,这对tc发展一点好处都没得,我觉得tc这种工具还是非常有意义的,和易语言按键精灵一样。希望tc的作者能够注意到吧,类比一下易语言和按键精灵,这仅仅是我个人之言,大家看看就行了。

本文用到的工具:
od
ida
等等

tc5和test程序:
链接: https://pan.baidu.com/s/19KjpJjp0ZqpekiYk-uJbgQ 提取码: x1q1 复制这段内容后打开百度网盘手机App,操作更方便哦

THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发
管埋员的头像-小北的自留地

昵称

取消
昵称