我目前正在对smali /"代码混淆器"进行一些研究,我正试图熟悉目前反编译的源代码.为此,我创建了一个简单的应用程序,并由smali反编译.
我现在正试图理解反编译的源代码,以便在以后使用代码混淆器后改进并比较安全性(反编译).虽然大多数小型源代码并不那么困难,但我有时会遇到数字格式转换的问题.
你可以向我解释一下如下.我猜它应该有五个值,但我不确定,这是哪种二进制格式.如何计算它0x4014 = 5 ???
const-wide/high16 v0, 0x4014 // 100000000010100 (5 = 101)
Run Code Online (Sandbox Code Playgroud)
附件是此测试函数的完整java和smali代码源:
Java来源:
boolean test(int a, double d) {
if (a < 5 && d < 5)
return true;
else
return false;
}
Run Code Online (Sandbox Code Playgroud)
Smali来源:
.method test(ID)Z
.locals 2
.parameter "a"
.parameter "d"
.prologue
.line 28
const/4 v0, 0x5
if-ge p1, v0, :cond_0
const-wide/high16 v0, 0x4014
cmpg-double v0, p2, v0
if-gez v0, :cond_0
.line 29
const/4 v0, 0x1
.line 31
:goto_0
return v0
:cond_0
const/4 v0, 0x0 …Run Code Online (Sandbox Code Playgroud) 我的问题如下:
在.NET,Java或Flash等较新的平台上,指令集是基于堆栈的操作码,JIT在运行时将其转换为本机格式.习惯于这种格式,我想知道如何执行和格式化"旧的"原生EXE格式.例如,"寄存器"通常在较新的平台操作码中不可用,因为JIT在其认为必要时将堆栈命令转换为16/32可用的CPU寄存器.但是在本机格式中,您需要通过索引引用寄存器,并确定可以重复使用哪些寄存器以及频率.
在shellcode教程中,我看到了以下示例:
main(){
exit(0);
}
Run Code Online (Sandbox Code Playgroud)
想法是创建一个exit() - 系统调用.那么,他们生产组件:
Section .text
global _start
_start:
mov ebx, 0
mov eax, 1
int 0x80
Run Code Online (Sandbox Code Playgroud)
我理解这一点.0是我们存储在ebx中的exit()的参数,1是退出系统调用的编号,使用0x80我们将CPU更改为内核模式并执行系统调用.
之后,他们让我们生成以下代码:
bb 00 00 00 00
b8 01 00 00 00
cd 80
Run Code Online (Sandbox Code Playgroud)
然后,他们将其翻译成C语言,看起来像:
char example[] = "\xbb\x00\x00\x00\x00"
"\xb8\x01\x00\x00\x00"
"\xcd\x80"
int main(){
int *pointer;
pointer = (int *)&pointer+2;
(*pointer) = (int)example;
}
Run Code Online (Sandbox Code Playgroud)
所以,我理解的是他们将操作码放在char数组中,但我不明白他们在main()中做了什么 - 方法.第一行还可以.但他们想用第2和第3行表达什么?
最好的祝福,
我的问题源于一个简单的好奇心:
为什么在x64中某些操作码是无效的(例如06,07),而在x86中用于相当基本的指令(06和07是推送和弹出)?我认为那些最简单的指令在两种架构中都能很好地完成.
为什么他们在x64中禁用了一些简单的指令?他们为什么不工作?为什么他们禁用某些操作码,在操作码列表中创建漏洞,何时可以将它们分配给x64版本的指令?
参考:
我正在查看说明及其相应的操作码.诸如"je"和"jz"之类的指令具有相同的操作码:
je,jz - 0x74 (8 bit)
je,jz - 0x0f84 (16/32 bit).
Run Code Online (Sandbox Code Playgroud)
为什么我们有这样的冗余指令?
是因为它使汇编编码更容易吗?也就是说,在某些情况下更容易理解"跳跃如果相等",而在其他情况下则更容易理解"跳跃于零".但是这些天我们并没有真正编写汇编代码,它有帮助吗?
我一直在玩IL,我注意到像Prefix1这样的OpCodes ,文档基本上告诉我不要担心它.当然,这让我很好奇这些各种前缀操作码实际上做了什么.一个快速的谷歌搜索没有发现任何东西,所以我想我会问这里的专家.有谁知道这些意味着什么?
如何知道字中的字节是表示16位指令还是32位指令?
我提到了ARM ARMv7M,我不清楚如何区分它是16位指令还是32位指令.
它说
If bits [15:11] of the halfword being decoded take any of the following values, the halfword is the first halfword of a 32-bit instruction:
• 0b11101
• 0b11110
• 0b11111.
Otherwise, the halfword is a 16-bit instruction
这是否意味着处理器总是取半字,检查它们并决定它是16位还是32位?
前半字是什么意思?一个字中的位[31-16]或位[15-0]?
如果我有32位,那么我可以知道它是32位指令还是16位指令?
谢谢.
我想我正在努力正确定义以下不明确的操作码:LD HL,SP+r8和JP (HL)操作码(0xE9和0xF8分别)
在我的实现中,LD HL,SP+r8设置HL为 的值SP+r8,但我感觉这可能与从 RAM 加载内存有关。
JP (HL),我已经PUSH将 PC 放到堆栈上并将程序计数器设置为 HL 的值(就像JP a16,除了 HL 的值),但我读过一些论坛,似乎说这是错误的。
任何对这些指令所做的任何澄清都会很棒,因为我现在很迷茫。
你为什么要用:
MOV EAX, 22
SHL EAX, 2
Run Code Online (Sandbox Code Playgroud)
...乘以4而不是仅仅使用MUL指令?
我知道这也可以用SHR而不是DIV.
这样做有什么好处?
你也可以用奇数做这个或者它只能是偶数吗?
我正在用C编写一个GameBoy颜色模拟器,只是为了介绍自己进入这个世界,它被解释,没有动态或静态重新编译:P
现在我正在执行C代码中所有CPU操作码的繁琐工作,我必须写下所有这些:http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html我不想从另一个模拟器中取出它们.
问题是,是否有某种方法可以自动执行操作码?也许这是一个愚蠢的问题,它会有一个愚蠢的答案,但我希望尽可能少地工作.:)
我在代码的各个地方都看过这个术语,比如图形编程样本.它似乎是一个C++语义,但显然有一个名为EmitCalli的C#/ .NET托管实现似乎与OpCodes.Calli有关.我认为这是一种机器语言指令.这个术语的解释是否与外行人的术语有些接近?
我不确定如何说出这个问题但是,我很想知道汇编程序和其他工具如何显示某些字节的操作码?
std::string BytesToOpcode( __in ::BYTE Bytes );
int main( void )
{
std::cout << BytesToOpcode( ( ::PBYTE )"\x33\xC0" );
std::cin.get( );
return( EXIT_SUCCESS );
};
// I don't know what type soo I'll just set as std::string for an example.
std::string BytesToOpcode( __in ::BYTE Bytes )
{
// Convert Bytes to opcode??
return( "" );
};
Output should be:
XOR EAX,EAX
Run Code Online (Sandbox Code Playgroud)