能力值:
( LV12,RANK:810 )
|
-
-
176 楼
最初由 luocong 发布
我刚才特意用OllyScript翻译了一次你的脚本,运行结果:
........
用小键盘的“-”号返回也没有找到原来的代码,我想可能是你设置的恢复原来代码的功能提前了。
|
能力值:
( LV13,RANK:370 )
|
-
-
177 楼
最初由 fxyang 发布
用小键盘的“-”号返回也没有找到原来的代码,我想可能是你设置的恢复原来代码的功能提前了。
请问如果是正确的话,应该是停在哪里?能不能贴那段反汇编代码出来?刚刚用OllyScript的脚本试了一下,按小键盘返回的第一个地方跟我的是一样的。附ODS的脚本:
var aOpenMutexA
EOE exception1 gpa "OpenMutexA", "kernel32.dll" mov aOpenMutexA, $RESULT bp aOpenMutexA
eob II2I run
exception1: //异常处理 esto //相当于Shift+F9,应该越过这个异常
II2I: exec PUSHAD PUSH EDX push 0 push 0 CALL CreateMutexA POPAD jmp OpenMutexA ende //完成双进程到单进程的转换 bc aOpenMutexA
|
能力值:
( LV12,RANK:810 )
|
-
-
178 楼
我也测试了,在
II2I:
后面加pause能停在OpenMutexA函数中,
现在这个OM运行到OpenMutexA函数中时没有停,好像是在内嵌汇编的入口处挂住了。pause后就停在
77EB6FE5 52 PUSH EDX //停在这里
77EB6FE6 68 00000000 PUSH 0
77EB6FEB 68 00000000 PUSH 0
77EB6FF0 E8 2346FAFF CALL kernel32.CreateMutexA
77EB6FF5 61 POPAD
77EB6FF6 ^ E9 ECB2FAFF JMP kernel32.OpenMutexA
如果用F8运行这个代码就会改变这段代码,出错!
|
能力值:
( LV12,RANK:810 )
|
-
-
179 楼
如果正确的话,这段代码应该运行完,然后停在kernel32.OpenMutexA函数的入口处
|
能力值:
( LV9,RANK:2130 )
|
-
-
180 楼
刚看一下就出问题了,请问变量怎么申明呀?直接用reg??,那样表示不好吧,不方便记忆,像osc那样直接var 变量 就方便记很多
|
能力值:
( LV13,RANK:370 )
|
-
-
181 楼
最初由 fxyang 发布 如果正确的话,这段代码应该运行完,然后停在kernel32.OpenMutexA函数的入口处
嗯!thanks
|
能力值:
( LV13,RANK:370 )
|
-
-
182 楼
最初由 loveboom 发布 刚看一下就出问题了,请问变量怎么申明呀?直接用reg??,那样表示不好吧,不方便记忆,像osc那样直接var 变量 就方便记很多
很遗憾,不支持声明变量,暂时来说只能改变一下习惯了。
|
能力值:
( LV9,RANK:2130 )
|
-
-
183 楼
再一个建议,建议把invoke给去掉直接 msg,msgyn等等,少打几个字嘛:D ,那样更方便我从osc上转过来.变量可以自己定义一个名字就最好了
|
能力值:
( LV13,RANK:370 )
|
-
-
184 楼
最初由 loveboom 发布 再一个建议,建议把invoke给去掉直接 msg,msgyn等等,少打几个字嘛:D ,那样更方便我从osc上转过来.变量可以自己定义一个名字就最好了
很遗憾,这两点都无法实现。
其实都是习惯问题了。在TASM里面连invoke宏都没有呢,所有的API都要先一个一个参数进行push,最后才来一个call,大家也还是能接受的。
至于变量的命名,我只能抱歉地说一句:目前我没有时间去做。OllyScript能做到这一点,是因为它用了CArray,不分青红皂白就把所有的变量保存在一个数组里了,不区分类型,由于没有任何语义检查,所以起变量名这个功能它实现起来比较简单,但代价是:
1、不严谨。这是我最无法容忍的。例如对一个字符串进行inc操作居然是允许的。
2、浪费内存,速度慢。
3、维护有一定的困难。
但我必须承认,从使用者的角度来看,越傻瓜化越好,然而作为一个开发者,我还是希望我的源代码是严谨而高效并且易于维护的。如果我要实现起变量名这个功能,我是肯定要去做语义检查的,但我目前没那么多时间。
将来等我没心思再去维护它的时候,按照惯例我会开源的。
|
能力值:
( LV12,RANK:810 )
|
-
-
185 楼
仔细的跟踪了内嵌汇编的过程,似乎在写入汇编代码的循环中没有出来。就是停在kernel32.OpenMutexA入口处停下的原因。
pause后F8会进入下面的代码:
03BD8720 53 PUSH EBX
03BD8721 56 PUSH ESI
03BD8722 8BF1 MOV ESI,ECX
03BD8724 57 PUSH EDI
03BD8725 8B7C24 10 MOV EDI,DWORD PTR SS:[ESP+10]
03BD8729 33DB XOR EBX,EBX
03BD872B 8B86 A0040000 MOV EAX,DWORD PTR DS:[ESI+4A0]
03BD8731 8D0C07 LEA ECX,DWORD PTR DS:[EDI+EAX]
03BD8734 8A4407 01 MOV AL,BYTE PTR DS:[EDI+EAX+1]
03BD8738 8886 E40C0000 MOV BYTE PTR DS:[ESI+CE4],AL
03BD873E 25 FF000000 AND EAX,0FF
03BD8743 2BC3 SUB EAX,EBX
03BD8745 74 2B JE SHORT OllyMach.03BD8772
03BD8747 48 DEC EAX
03BD8748 75 5D JNZ SHORT OllyMach.03BD87A7
03BD874A 8BCE MOV ECX,ESI
03BD874C E8 EF000000 CALL OllyMach.03BD8840
03BD8751 85C0 TEST EAX,EAX
03BD8753 74 52 JE SHORT OllyMach.03BD87A7
03BD8755 8B8E A0040000 MOV ECX,DWORD PTR DS:[ESI+4A0]
03BD875B 8B86 E00C0000 MOV EAX,DWORD PTR DS:[ESI+CE0]
03BD8761 85C0 TEST EAX,EAX
03BD8763 8B540F 02 MOV EDX,DWORD PTR DS:[EDI+ECX+2]
03BD8767 8B8C96 EF0C0000 MOV ECX,DWORD PTR DS:[ESI+EDX*4+CEF]
03BD876E 74 37 JE SHORT OllyMach.03BD87A7
03BD8770 EB 0D JMP SHORT OllyMach.03BD877F
03BD8772 8B86 E00C0000 MOV EAX,DWORD PTR DS:[ESI+CE0]
03BD8778 8B49 02 MOV ECX,DWORD PTR DS:[ECX+2]
03BD877B 85C0 TEST EAX,EAX
03BD877D 74 28 JE SHORT OllyMach.03BD87A7
03BD877F 8B96 EA0C0000 MOV EDX,DWORD PTR DS:[ESI+CEA]
03BD8785 48 DEC EAX
03BD8786 83C2 FC ADD EDX,-4
03BD8789 8986 E00C0000 MOV DWORD PTR DS:[ESI+CE0],EAX
03BD878F 8996 EA0C0000 MOV DWORD PTR DS:[ESI+CEA],EDX
03BD8795 898C86 E0040000 MOV DWORD PTR DS:[ESI+EAX*4+4E0],ECX //这里好像写入了什么
03BD879C 5F POP EDI
03BD879D 5E POP ESI
03BD879E B8 01000000 MOV EAX,1
03BD87A3 5B POP EBX
03BD87A4 C2 0400 RETN 4
然后进入这个循环:
03BDC11A 8B96 A0040000 MOV EDX,DWORD PTR DS:[ESI+4A0]
03BDC120 8B86 E60C0000 MOV EAX,DWORD PTR DS:[ESI+CE6]
03BDC126 B9 04000000 MOV ECX,4
03BDC12B 8A0402 MOV AL,BYTE PTR DS:[EDX+EAX]
03BDC12E 8886 E50C0000 MOV BYTE PTR DS:[ESI+CE5],AL
03BDC134 25 FF000000 AND EAX,0FF
03BDC139 83F8 6D CMP EAX,6D
03BDC13C 0F87 FF130000 JA OllyMach.03BDD541
03BDC142 FF2485 A8D6BD03 JMP DWORD PTR DS:[EAX*4+3BDD6A8]
03BDC149 FF86 E60C0000 INC DWORD PTR DS:[ESI+CE6]
03BDC14F E9 F3130000 JMP OllyMach.03BDD547
03BDC154 8B8E E60C0000 MOV ECX,DWORD PTR DS:[ESI+CE6]
03BDC15A 6A 02 PUSH 2
03BDC15C 51 PUSH ECX
03BDC15D 8BCE MOV ECX,ESI
03BDC15F E8 ACCBFFFF CALL OllyMach.03BD8D10
03BDC164 3BC7 CMP EAX,EDI
03BDC166 75 06 JNZ SHORT OllyMach.03BDC16E
…………
03BDD552 3BC5 CMP EAX,EBP
03BDD554 75 26 JNZ SHORT OllyMach.03BDD57C
03BDD556 8B86 E60C0000 MOV EAX,DWORD PTR DS:[ESI+CE6]
03BDD55C 3BC7 CMP EAX,EDI
03BDD55E 7C 12 JL SHORT OllyMach.03BDD572
03BDD560 3B86 A4040000 CMP EAX,DWORD PTR DS:[ESI+4A4]
03BDD566 7F 0A JG SHORT OllyMach.03BDD572
03BDD568 8BC5 MOV EAX,EBP
03BDD56A 8986 C0040000 MOV DWORD PTR DS:[ESI+4C0],EAX
03BDD570 EB 0E JMP SHORT OllyMach.03BDD580
03BDD572 33C0 XOR EAX,EAX
03BDD574 8986 C0040000 MOV DWORD PTR DS:[ESI+4C0],EAX
03BDD57A EB 04 JMP SHORT OllyMach.03BDD580
03BDD57C 3BC7 CMP EAX,EDI
03BDD57E 74 0C JE SHORT OllyMach.03BDD58C
03BDD580 39AE C0040000 CMP DWORD PTR DS:[ESI+4C0],EBP
03BDD586 ^ 0F84 8EEBFFFF JE OllyMach.03BDC11A //循环开始
老罗参考看看,是不是运行内嵌代码的处理过程有问题。
|
能力值:
( LV12,RANK:730 )
|
-
-
186 楼
给OllyMachine提点改良的建议
1.
改变 API 进行操作时返回的错误或失败是为-1的值,为何不能改为返回0,或者你只需要将-1求反就能变为0
cmp reg00,-1
cmp reg00,0xffffffff
cmp reg00,0
cmp reg00,0x0
// 由此可看出,用 0 作为失败,比用 -1 作为失败要简化,我相信变成汇编机器码表示 0 要比表示-1要来得省和好,不知对不对?
2.
ReplaceBytes address, find, repl, len
// 这条 API 似乎功能不够灵活实用,len 能否改为这样定义:len是从 address 开始搜索替换的范围(长度),比如:
invoke replacebytes,401000,0xcc,0x90,1000
// 表示从401000到402000的范围内,替换所有cc为90,402000 就是等于 address+len
// 另外,返回值可送到 reg00,表示替换的数量,0 表示没有成功,非 0 表示成功数量,似乎“返回找到的地址”意义不大(因为 find)
3.
// nop API作用没什么必要吧,就删除它行吧?我不知道它对你修bug有什么作用...
4.
find 和 search API 如果没有区别,没必要开多其中一个
5.
__asm
{
pushfd
pushad
push 0
call GetModuleHandleA
cmp eax,0
je lbl1
push // 1.6版本的(1.7没到手),居然编译成功这里为何不出语法错误
popad
popfd
jmp end
lbl1:
popad
popfd
push 0
call ExitProcess
end:
nop
}
invoke msg,"Great,run perfect!"
//内嵌不知是否支持标签,运行结果没有达到目的,eax最终为程序模块值。
|
能力值:
( LV13,RANK:370 )
|
-
-
187 楼
真诚感谢fxyang!我先收藏你的研究结果,回头对比一下代码。
|
能力值:
( LV13,RANK:370 )
|
-
-
188 楼
感谢askformore提供那么多的改良建议!我来解释一下:
1. 改变 API 进行操作时返回的错误或失败是为-1的值,为何不能改为返回0,或者你只需要将-1求反就能变为0
有些API的返回值如果用0来表示错误的话,是不够严谨的。我举个例子:
invoke ReadMemLong, eip, 4
有可能读到的数据本身就是0,这时如果用0来表示错误的话,那么就是一个bug了。但诚如你所说的,用0是最方便的,不过既然现在已经用-1了,那就不改了,否则以前别人写过的一些脚本可能就出错了。
2. ReplaceBytes address, find, repl, len // 这条 API 似乎功能不够灵活实用,len 能否改为这样定义:len是从 address 开始搜索替换的范围(长度),比如:
invoke replacebytes,401000,0xcc,0x90,1000 // 表示从401000到402000的范围内,替换所有cc为90,402000 就是等于 address+len // 另外,返回值可送到 reg00,表示替换的数量,0 表示没有成功,非 0 表示成功数量,似乎“返回找到的地址”意义不大(因为 find)
这个建议非常好,我会新增一个API来实现这个功能。
3. // nop API作用没什么必要吧,就删除它行吧?我不知道它对你修bug有什么作用...
对一般的应用来说的确是没用的,但它有个特殊的用处,是用在虚拟机内部的:我在OllyMachine的指令集里面,把NOP指令的opcode设置为0,这意味着如果虚拟机遇到了特殊的情况(比如异常)导致跑“飞”了,而跑飞的地方的数据是0(这是很有可能的),那么虚拟机会认为这个地方是NOP,从而可以继续运行下去,只不过是多浪费一个指令周期而已。
4. find 和 search API 如果没有区别,没必要开多其中一个
Find和Search还是有区别的,区别在于:
Search与Find的不同之处在于,Search并不会从一个合法的Opcode的起始地址开始搜寻。
例如:
004010DC 55 PUSH EBP 004010DD 8BEC MOV EBP,ESP 004010DF 6A FF PUSH -1
如果用invoke Find, eip, "EC6AFF",那么不会找到,返回-1;
如果用invoke Search, eip, "EC6AFF",那么会返回004010DE。
5. __asm { pushfd pushad push 0 call GetModuleHandleA cmp eax,0 je lbl1 push // 1.6版本的(1.7没到手),居然编译成功这里为何不出语法错误 popad popfd jmp end
lbl1: popad popfd push 0 call ExitProcess
end: nop } invoke msg,"Great,run perfect!"
//内嵌不知是否支持标签,运行结果没有达到目的,eax最终为程序模块值。
1、在0.17版里面,我重写了内嵌汇编的词法和语法分析器,上面所提到的push这条指令没有被检测出来,的确在0.16里面存在,但在0.17里面已经不会出现了。
2、内嵌不支持标签。我会在将来的版本中继续改进内嵌汇编的功能。
最后补充一句:有的时候也许会觉得OllyMachine的一些设计上存在很不可思议的地方,这很可能是历史遗留问题导致的,例如刚刚开始没有考虑到某种情况,然后在使用者的反馈下我决定新增某个功能...
|
能力值:
( LV2,RANK:10 )
|
-
-
189 楼
支持,我来晚了。
|
能力值:
(RANK:215 )
|
-
-
190 楼
喝多了,再来顶一下小罗。:o
|
能力值:
( LV13,RANK:370 )
|
-
-
191 楼
to fxyang:
我后来重新跟踪了一次OllyMachine的源代码,发现并不是OM的bug。我修改了一下你的脚本,如下,可以正确运行了:
EOE OnException1
invoke GetProcAddress, "OpenMutexA","kernel32.dll" mov reg01,reg00 invoke bp reg01 eob II2I mov reg10, -1 // 设置一个标志位,用来表示是否已经运行过嵌入汇编了 run
OnException1: // 异常处理 esto // 相当于Shift+F9,应该越过这个异常
II2I:
// 完成双进程到单进程的转换 invoke bc reg01
cmp reg10, -1 // 是否已经运行过嵌入汇编了? jne II2I_End // 没有运行过,这是第一次
mov reg10, 0 // 标志位设置为非-1即可,以后就不会再运行了
__asm { PUSHAD PUSH EDX push 0 push 0 CALL CreateMutexA POPAD jmp OpenMutexA }
II2I_End: invoke msg, "现在我们位于OpenMutexA函数体的第一条指令了!"
其实关键的地方在于脚本的逻辑有问题。应该判断一下是否已经到达过OpenMutexA的函数体了,否则就会陷入一个死循环中。
不知道我对你的脚本的逻辑的理解是否正确?请指教。
|
能力值:
( LV12,RANK:810 )
|
-
-
192 楼
OK,修改的OM能运行了,只是我不能理解为什么要判断是不是运行过内嵌汇编?运行一次就应该到下面的语句了,是什么造成循环的呢?脚本中没有这个循环呀?
|
能力值:
( LV13,RANK:370 )
|
-
-
193 楼
最初由 fxyang 发布 OK,修改的OM能运行了,只是我不能理解为什么要判断是不是运行过内嵌汇编?运行一次就应该到下面的语句了,是什么造成循环的呢?脚本中没有这个循环呀?
这个跟OllyMachine虚拟机的内部实现有关,现在我正在写0.18的文档,等一会再说……
|
能力值:
( LV12,RANK:810 )
|
-
-
194 楼
期待你的完美:p
|
能力值:
( LV2,RANK:10 )
|
-
-
195 楼
正看着要下
突然变出0.18版了
升级好快:p
|
能力值:
( LV13,RANK:370 )
|
-
-
196 楼
OllyMachine 0.18版发布。
地址: http://www.luocong.com/om
更新如下:
1. 新增:两个新的搜索API:
* ReverseFind
* ReverseSearch
2. 新增:两个新的替换API:
* CopyBytesTo
* ReplaceBytesEx
3. 修正:在Search中的一个bug,有时会导致无法找到正确的地址。
说明:
1、ReverseFind和ReverseSearch的功能跟Find和Search一样,唯一的区别在于它们是往前进行搜索的。
2、CopyBytesTo的示例:
invoke CopyBytesTo, eip, 0x401000, 10
它的作用是把eip处的10个字节拷贝到0x401000处。
3、ReplaceBytesEx的示例:
invoke ReplaceBytesEx, eip, 10, "60e8??", "909090"
它的作用是,从eip开始,在10个字节范围内,把"60e8??"替换成"9090??"。注意事项:
1、准备替换的字节数和替换成的字节数必须相同。例如假如源码为"60e8??",表示3个字,那么替换成的字节码也必须是3个字节。
2、在源码里面的"??"不会被替换。例如假如源码为"60e8??",替换成的字节码为"123456",
那么替换后将会是"1234??",原来的"??"所表示的那个字节不变。
|
能力值:
( LV2,RANK:10 )
|
-
-
197 楼
:D thx
|
能力值:
( LV2,RANK:10 )
|
-
-
198 楼
升级得好快。。。。等稍微稳定了,再下载来好好学;)
|
能力值:
(RANK:10 )
|
-
-
199 楼
|
能力值:
( LV2,RANK:10 )
|
-
-
200 楼
最初由 玉川 发布 升级得好快。。。。等稍微稳定了,再下载来好好学;)
越测试,越稳定
|
|
|