一、前言

最近接触了一个QBasic编写的16位程序的逆向,该程序是运行在纯DOS环境下,虽然此环境已离我们远去,能接触到的机会不是太多,但为了防止有意外碰到的同学像我最开始那样走弯路,特此将该笔记整理一下发出,希望对需要的同学有些帮助.由于时间仓促,研究不深文中难免有错误之处,欢迎各高手指教.

QBasic7.1是微软公司推出的一套基于Basic语言的集成开发环境,虽然在当时来说此开发环境功能已经非常强大,但相对于现如今我们这些用惯了Visual Studio, Eclipse等更加强大的人来说,那个环境就有点太老土了.因此我们得换一套更有效率的环境,我用的是SlickEdit 15.0.0.5,至于编译我写了一个简单的批处理来完成.

注: 由于在不同的编译参数下可能会生成不同的程序结构,因此本文只讨论如下参数生成的程序

BC test.bas/V/D/O/FPi/G2/Ot/Lr/Fs/Zi/T/C:512;

其它的差别不大,同学们可以自己研究下 J

二、必要的结构

1: QBasic程序的结构

程序由多个SEGMENT组成,具体结构如下:

注1:用IDA打开目标EXEà”CTRL+E”à选择”入口点”,此时将停在”启动代码”处.

注2:按编译链接时的顺序每个OBJ文件对应一个SEGMENT

2: BAS源文件所在SEGMENT的结构:

上图中的”BAS源文件”对应若干个SEGMENT(取决于有多少个OBJ文件),而每个SEGMENT都是如下的一个结构:

这个”SegHdr”是个管理结构,范围是当前段(SEGMENT),大小为30H.

该结构包含了对应的BAS文件的文件名,各个数据段的偏移等.

每个BAS文件在链接后对应着程序中的一个SEGMENT,段头的前10个字节就是该文件的文件名.这些SEGMENT是按编译顺序排放的.之所以这里会是10个字节因为每个名字都有一个”bl”前缀.

在所有的OBJ合并到EXE中之后,这些段名是不见的,它们都变成了同一个段中的不同偏移位置.

3: 代码结构

每一个SEGMENT的真正代码都是从30H处开始,大致结构如下:

由上图可以看出,所有写在SUB/FUNCTION中的函数都会被这些JMP指令路过.

而那些没写在任何SUB/FUNCTION块中的代码将被执行.也就是QBasic中没一个像C语言那样的main()函数.

三、开始逆向

关于结构方面的东西介绍完了,下面再来看一下跟逆向有实质性关联的东西吧.

1: 参数传递与调用方式

QBasic函数的参数是从左向右压栈的.由本函数负责清理.

参数默认情况下是通过引用传递的,所以在函数内部修改参数值是会影响到外面的.

如:CALL TestSub(1, 2, 3)将会生成如下代码

mov word ptr [bp - 14h], 1

mov word ptr [bp - 16h], 2

mov word ptr [bp - 18h], 3

lea ax, [bp-14h]

push ax

lea ax, [bp-16h]

push ax

lea ax, [bp -18h]

push ax

call TestSub

如果要进行传值调用需要在函数声明时添加BYVAL 说明.

2: 识别库函数

这个可以说是整个逆向过程中最重要的一步了,如果库函数无法识别工作量将会扩大N倍.

但由于IDA本身没有带QBasic的符号,所以在开工之前需要把QB安装目录中的库文件做成

SIG符号文件.记得保留那些中间(PAT)文件,防止IDA不能自动识别时用来手动识别.

具体的制作方法可以去网上搜下教程,这里就不讨论了.

3: 库函数的转换

在QBasic中库函数的名字一般都有个前缀”B$”以此来防止与正常的函数重名.因此即使完成了库函数识别也无法开始工作,还得做一步额外的工作:库函数到接口函数的转换.

这个工作是由编译器在编译时完成的,现在我们反过来操作难度有点大,但好在QBasic的库函数也不是很多,我用了一个比较土的方法:在Google中搜索BAS文件以及相应的OBJ文件并加以人肉分析对比,这样便可以建立起一个对应表, 如:

B$GOSA============= GOSUB SubName

B$FCHR============= CHR$(n)

B$SAS1============== FileName& = "xxxxxxx"

B$PEI2 ============== PRINT x%

B$PSSD============== PRINT "xxxxxxxx";

B$SSHL============== SHELL "xxxxx"

………………….

(限于篇幅有限,就不贴完整的了)

4: 对于READ处理

QBasic中READ和DATA是相对出现的,DATA用来定义一个数据集,而READ则从这些数据集中取出数据给变量赋值.如:

DATA AAA, BBB, CCC, DDD, EEE

FOR I = 0 TO 4

READ KKK$

PRINT KKK$

NEXT I

与之对应的部分汇编代码如下:

…….

push   ds

push   offset kkk

xor     ax, ax

push   ax

call    B$RDSD ==== READ

push   offset kkk

call    B$PESD ==== PRINT

……..

这里, DATA去哪了呢?

嗯….来到该代码所在的SegHdr部分,那个Off2指向的区域(即BC_DS段)就包含了这些DATA数据.

5: 需要注意的地方

1)这里特别需要注意的就是QBasic中变量在使用前可以不用声明,因此如果出现如下代码,编译器也不会报错,但结果就大不一样了:

var10 = 1: var12 = 2: var14 = 3: var16 = 4

CALL TestSub(var10, var13, var14, var16)

这里由于手误将”var12”写成了”var13”编译器是发现不了的.

2)所有函数在调用之前都应该声明,否则会被当成数组或变量.

至此都已经差不多了,剩下的都是些体力活了~

四、致谢

在此期间收到了很多的朋友的帮助与技术支持,特别要感谢Pete’s的burger2227与qb_liu.

本文欢迎转载,但请保证信息完整.如有不清楚的欢迎讨论.

thinkSJ (于南京)

五、参考资料

1: PC Magazine's BASIC Techniques and Utilities  by Ethan Winer

http://www.ethanwiner.com

2:  Pete's QBASIC Site

http://www.petesqbsite.com

3: QB CULT MAGAZINE

http://qbcm.hybd.net

逆向QBasic7.1笔记相关推荐

  1. 滴水逆向win32学习笔记1

    滴水逆向win32学习笔记 一.字符编码 基本介绍 关于utf-16.utf-8和unicode的关系 BOM头 二.宽字符 基本介绍 常用函数 三.Win32 API中的宽字符 什么是win32 A ...

  2. OD逆向调试程序的笔记

    1-读取文本框内容常用的函数(这里的"A"表示ASCII,"W"表示宽字符UNICODE,下同)   -GetDlgItemTextA()<这个函数是最常 ...

  3. 滴水逆向3期笔记与作业——01汇编

    防止OneNote丢失. 海哥牛逼. 01汇编笔记 01进制 进制定义 10-2进制转换 八进制 02数据宽度/逻辑运算 数据宽度与存储 逻辑运算 计算机做加法的本质 作业 03通用寄存器_内存读写 ...

  4. 180728 逆向-SMC出题笔记

    在某黑哥的指示下给他加紧出两个题目~ 最先想到的就是34c3ctf时做过的SMC题目,那个随机数混杂着自解密真的是让我久久无法忘怀 SMC题目的核心就在于自解密时的key 如果key不提供,那么考点就 ...

  5. 静态链接库,动态链接库【滴水逆向三期48笔记】

    在开发过程中,我们通常会有很多函数,需要多次使用或在不同的程序中使用该函数,也有可能我们会将我们写好的函数给别人使用,但是我们又不想给他源代码,毕竟代码是我们花了很多功夫写出来的,那么我们如何不发给其 ...

  6. IAT表入门简析【滴水逆向三期52笔记】

    在讲IAT表之前,我们来回忆一下之前学习的知识: 如果我们将函数写在程序的源文件中,那么该函数就会被编译器直接编译到程序的二进制文件中,在程序调用该函数的时候,E8后跟的地址是直接写死的,程序直接在e ...

  7. 导入表解析,IAT表解析【滴水逆向三期53笔记】

    我们再上一章节简要介绍了IAT表,我们知道如果程序调用dll中的函数时,必须通过IAT表来找到函数,我们基本了解了IAT表之后,我们今天来讲解一下导入表,通过本章节的学习,我们可以了解导入表,也能对I ...

  8. android studio 修改包名_android逆向笔记之初学者常用adb命令

    android逆向常用命令笔记 1.如何导出已安装apk? a.列出已经安装的包 | grep -i 关键字 b.找出安装路径 adb shell pm path 包名 c.拉下来: adb pull ...

  9. adb命令 android 串口_android逆向笔记之初学者常用adb命令

    android逆向常用命令笔记 1.如何导出已安装apk? a.列出已经安装的包 adb shell pm list package | grep -i 关键字 b.找出安装路径 adb shell ...

最新文章

  1. SAP MM MIGO界面里的'Delivery completed'标记
  2. dubbo 源码编译记录
  3. 离线安装Cloudera Manager 5和CDH5(最新版5.9.3) 完全教程(七)界面安装
  4. ubuntu无线网络开关
  5. Linux下多线程模拟停车场停车
  6. AWS CEO Andy Jassy 专访:我们一直思考的是未来 2-5 年的事 | 人物志
  7. (STL,set)安迪的第一个字典
  8. 关于心理的二十五种倾向(查理#183;芒格)-2
  9. mysql workbench首页_MySQL Workbench是干什么的?
  10. KL散度、JS散度以及交叉熵对比
  11. Day10--路由嵌套+项目前后台搭建
  12. C语言实现线性回归求斜率
  13. 年末大盘点 2008十大最受欢迎的装机软件
  14. ubuntu离线安装免费版本Typora
  15. 【办公必备软件】万彩办公大师教程丨PDF转HTML工具
  16. Gentoo虚拟机安装--基于分发内核
  17. java列表末尾添加元素_在迭代它时将元素添加到Java LinkedList的末尾
  18. 濒临死亡的校园BBS
  19. 编辑距离WER/CER计算的一种python实现
  20. can总线不加末端电阻_高手写的CAN总线入门总结,对全面理解CAN总线特性很有帮助...

热门文章

  1. 电商平台API接口,店铺所有商品
  2. LNMP详解(七)——Nginx反向代理配置实战
  3. android自定义view圆环,Android自定义View实现圆环进度条
  4. 牛客小白月赛6 J 洋灰三角
  5. python 自动编写新闻_Python多篇新闻自动采集
  6. 路由器密码 $1$$zdlNHiCDxYDfeF4MZL.H3/
  7. 工地wifi认证登录哪里有
  8. 质监局监督检测指挥系统
  9. 异常:calling prepareStatement is no longer allowed! Increase reapTimeout to avoid this problem
  10. html游戏社区豳风破斧,诗经·豳风——《破斧》