首页
社区
课程
招聘
[原创]一次简单的powerbuilder逆向及修改
2022-11-10 10:30 992

[原创]一次简单的powerbuilder逆向及修改

2022-11-10 10:30
992

感谢坛友的工具PbdViewer v0.1,另外还用到了PowerBuilder-decompile

 

单位某系统因为等保整改要求改了数据库密码,结果导致为其定制的数据传输工具无法工作,乙方则因开发离职和交接问题也无法提供支援,只好尝试自己搞了。

 

打开工具对应ini配置文件,里面对应连接串部分只有两行对应服务器地址和数据库名称:

1
2
3
[database]
SERVERNAME=192.168.3.3
DATABASE=cw30

工具目录下有七八个pbd文件,先用hex编辑器逐个打开搜索关键词(ini文件名,及SERVERNAME变量名),找到后再用PbdViewer 逐个打开查看,很快定位到main.pbd文件下的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//public function integer gf_connect_cw()
 
string ls_dbname
string ls_server
string ls_err
string ls_current_directory
string ls_accfile
nvo_public_function iuo_pub
 
 
gtr_cw = create transaction
disconnect using gtr_cw;
ls_current_directory = iuo_pub.uf_directory_getcurrent()
if not fileexists(ls_current_directory + "\CONN.INI") then
    messagebox("msg: ",ls_current_directory + "\CONN.INI not exist",information!)
    return -1
end if
ls_accfile = ls_current_directory + "\CONN.INI"
ls_dbname = profilestring(ls_accfile,"database","DATABASE","")
ls_server = profilestring(ls_accfile,"database","SERVERNAME","")
if ls_dbname <> "" then
    gtr_cw.dbms = "OLE DB"
    gtr_cw.servername = ls_server
    gtr_cw.database = ls_dbname
    gtr_cw.logid = "cw_" + ls_dbname
    gtr_cw.logpass = ls_dbname
    gtr_cw.autocommit = false
    gtr_cw.dbparm = "PROVIDER='SQLOLEDB',DATASOURCE='" + ls_server + "',PROVIDERSTRING='database=" + ls_dbname + "'"
    gtr_cw.lock = "RC"
    connect using gtr_cw;
    if gtr_cw.sqlcode <> 0 then
        messagebox("msg","connecting database error" + ls_dbname + ",Error:~r~n" + ls_err + "~r" + left(gtr_cw.sqlerrtext,len(gtr_cw.sqlerrtext) - 1))
        return -1
    end if
end if
return 1
return

可以看到连接串部分用库名+固定前缀用作用户名,库名本身就是密码,所以改密码之后就无法连接了。如果有源码的话,就可以在ini配置文件里加上用户密码项,然后修改函数里读文件的部分来读取用户密码。

 

不过现在只能想别的办法,比如用hex工具直接修改pbd文件伪码。如果只是删改比较简单,但现在直观的办法是要添加变量并赋值,按以前逆asm的经验这需要在代码区和数据区找到空余并添加内容,这对第一次面对powerbuilder的我来说实在有点困难。瞪着代码思考良久的我突然灵光一闪,既然只改了密码,那干脆用配置文件里SERVERNAME项来放密码不就行了吗,至于数据库地址,可以在hosts里把密码绑上目标IP啊(幸好新密码只有数字+大小写字母)!于是接下来的事就非常简单了。

 

修改ini文件:

1
2
3
[database]
SERVERNAME=nUPaSsw0Rd
DATABASE=cw30

host文件添加:

1
192.168.3.3 nUPaSsw0Rd

接下来只需要把函数里

1
gtr_cw.logpass = ls_dbname

改成

1
gtr_cw.logpass = ls_server

此时就用到了另一个工具PowerBuilder-decompile,先将pbd文件dump一下:

1
pbd_dump.py main.pbd

在输出的一大堆文件里找到函数对应文件gf_connect_cw.fun,再进一步解析该文件:

1
analyse.py main-pbd\gf_connect_cw.fun

接下来就能获得gf_connect_cw.code和gf_connect_cw.debug两个文件了,前者基本等同PbdViewer解析出的源码,后者就是对应的伪码,两个文件里有行号可以对应。

 

源码gf_connect_cw.code里面丢了变量名,不过影响不大

1
2
3
4
23:  gtr_zw.:string = ls_server
24:  gtr_zw.:string = ls_dbname
25:  gtr_zw.:string = "cw_" + ls_dbname
26:  gtr_zw.:string = ls_dbname

伪码gf_connect_cw.debug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
line 23:
    SM_PUSH_LOCAL_GLOBREF (16)
    SM_PUSH_CONST_REF (256, 0)
    SM_DOT_LV (2)
    SM_PUSH_LOCAL_VAR (1)
    SM_COPY_LVALUE_STRING (1)
    SM_ASSIGN_STRING (2)
line 24:
    SM_PUSH_LOCAL_GLOBREF (16)
    SM_PUSH_CONST_REF (264, 0)
    SM_DOT_LV (2)
    SM_PUSH_LOCAL_VAR (0)
    SM_COPY_LVALUE_STRING (1)
    SM_ASSIGN_STRING (2)
line 25:
    SM_PUSH_LOCAL_GLOBREF (16)
    SM_PUSH_CONST_REF (272, 0)
    SM_DOT_LV (2)
    SM_PUSH_CONST_STRING (280, 0)
    SM_PUSH_LOCAL_VAR (0)
    SM_CAT_STRING ()
    SM_POP_POP ()
    SM_ASSIGN_STRING (2)
line 26:
    SM_PUSH_LOCAL_GLOBREF (16)
    SM_PUSH_CONST_REF (288, 0)
    SM_DOT_LV (2)
    SM_PUSH_LOCAL_VAR (0)
    SM_COPY_LVALUE_STRING (1)
    SM_ASSIGN_STRING (2)

现在我们要把行26的 gtr_cw.logpass = ls_dbname 改成 gtr_cw.logpass = ls_server,对比下行23和行24的伪码,SM_PUSH_LOCAL_VAR 这里貌似就是赋值的关键了,大概只要把行26的SM_PUSH_LOCAL_VAR (0) 改成SM_PUSH_LOCAL_VAR (1)就行了。

 

接下来就是找到伪码对应的hex值,在PowerBuilder-decompile里的pcode.py可以直接查到

1
2
3
4
5
6
{'index': 0x20, 'name': 'SM_PUSH_CONST_REF', 'arg_num': 2, 'unknown': 0x1, 'addr': 0x10d54b00, 'func': pb_push_const},
{'index': 0x2f, 'name': 'SM_PUSH_LOCAL_GLOBREF', 'arg_num': 1, 'unknown': 0x1, 'addr': 0x10d55100, 'func': pb_push},
{'index': 0x122, 'name': 'SM_DOT_LV', 'arg_num': 1, 'unknown': 0xffffffff, 'addr': 0x10d57200, 'func': pb_dot},
{'index': 0x1e, 'name': 'SM_PUSH_LOCAL_VAR', 'arg_num': 1, 'unknown': 0x1, 'addr': 0x10d54650, 'func': pb_push},
{'index': 0x139, 'name': 'SM_COPY_LVALUE_STRING', 'arg_num': 1, 'unknown': 0x0, 'addr': 0x10d59cf0, 'func': pb_empty},
{'index': 0x88, 'name': 'SM_ASSIGN_STRING', 'arg_num': 1, 'unknown': 0xfffffffe, 'addr': 0x10d4d0b0, 'func': pb_assign},

伪码操作数长度都是word,行26对应的完整hex就应该是

1
2
0000081ah: 2F 00 10 00 20 00 20 01 00 00 22 01 02 00 1E 00 ;
0000082ah: 00 00 39 01 01 00 88 00 02 00                   ;

把SM_PUSH_LOCAL_VAR (0)改成(1),对应的hex就是1E 00 00 00 改成1E 00 01 00

 

最后用hex工具打开main.pbd,搜索
2F 00 10 00 20 00 20 01 00 00 22 01 02 00 1E 00 00 00 39 01 01 00 88 00 02 00
替换
2F 00 10 00 20 00 20 01 00 00 22 01 02 00 1E 00 01 00 39 01 01 00 88 00 02 00

 

保存后用PbdViewer 打开验证,函数内代码变成了

1
2
3
4
gtr_cw.servername = ls_server
gtr_cw.database = ls_dbname
gtr_cw.logid = "cw_" + ls_dbname
gtr_cw.logpass = ls_server

执行main.exe文件,数据库连通,数据传输功能ok,工作完成!

 

既没有混淆也没有加壳就还蛮简单的


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回