我已经获得了以下加密程序:它实际上使用的是EKey var(I)和temp_char var,它等于数组I中的第一个,第二个,第三个等等字符根据所包含的for循环的迭代进行传递。
我尽力发表评论并尽力理解。
以下注释值来自查看' watch'中的寄存器/值。在视觉工作室,并假设我进入" aaaa"作为我的测试字符串。
注意:EChars是一个早期在程序中定义的数组,但我并不认为有必要提及它,除了它最多可以容纳6个字符并且是以$结尾。 与DChars相同。
void encrypt_chars (int length, char EKey)
{ char temp_char; // Character temporary store
for (int i = 0; i < length; i++) // Encrypt characters one at a time
{
temp_char = OChars [i]; // Get the next char from Original Chars array
__asm {
push eax // Prepare the EAX register to store volatile memory.
push ecx // Prepare the ECX register to store volatile memory.
// Removes whatever value is stored in there to start with.
// Pushing pushes the value (not stored in a register necessarily) and writes it into the stack
movzx ecx,temp_char // Moves the char with zeroes, meaning that the temp_char value has 0s at the beginning
lea eax,EKey // Loads the address of the Ekey currently in memory, into the EAX register
push ecx // Push ecx to the top of the stack. Stores char
push eax // Stores address of ekey
call encrypt_17 // Calls the encyrption routine below, before jumping back up to the line below
add esp, 8 // Adding 8 to the stack pointer moves the pointer to (somewhere in the stack, I'm unsure where)
mov temp_char,al // AL is the last 8 bits of the EAX register, what happens here is that AL is then moved into
// the temp_char value, after it has been encrypted; modifying the value before storing it into the EChars array
pop ecx // Restore original register values
pop eax // ""
}
EChars [i] = temp_char; // Store encrypted char in the Encrypted Chars array location depending on loop
}
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm {
encrypt_17:
push esi
push ecx //temp char t = 116 first time around
mov esi, eax //sets eax to esi, which has a value of '2422272'
and dword ptr[esi], 0xFF
ror byte ptr[esi], 1
ror byte ptr[esi], 1 //these two lines set Ekey I(72) to Ekey R(82) (inc by 10?)
add byte ptr[esi], 0x01 //adds 1 to the ekey, changing it to S
mov ecx, [esi] //move location of Ekey (S) to ECX
pop edx //restore original val of edx (which appears to be 116 (temp char, t from 'test')
x17 :
ror dl, 1 //dl = t, after this it's set to 58 ':', edx is also set to 58,
//second time through sets edx to 29 and dl to 29 '\x1d'
dec ecx //decrement ecx to 82 from 83,
jnz x17 //goes until ecx is 0
mov eax, edx //eax gets set to 142. which is 'Z' with an arrow above it
add eax, 0x20 //eax gets set to 174, from 154
xor eax, 0xAA //XOR'ing 154 with AA sets it to 4
pop esi //ECX gets set to 0
ret //value gets returned
}
以下是我到目前为止的解密尝试:
void decrypt_chars (int length, char EKey)
{ char temp_char; // Character temporary store
for (int i = 0; i < length; i++) // Encrypt characters one at a time
{
temp_char = EChars[i]; // Get the next char from Encrypted Chars array
__asm {
push eax // Prepare the EAX register to store volatile memory.
push ecx // Prepare the ECX register to store volatile memory.
// Removes whatever value is stored in there to start with.
// Pushing pushes the value (not stored in a register necessarily) and writes it into the stack
movzx ecx, temp_char // Moves the char with zeroes, meaning that the temp_char value has 0s at the beginning
lea eax, EKey // Loads the address of the Ekey currently in memory, into the EAX register
push ecx // Push ecx to the top of the stack. Stores char
push eax // Stores address of ekey
call decrypt_17 // Calls the encyrption routine below, before jumping back up to the line below
add esp, 8 // Adding 8 to the stack pointer moves the pointer to...
mov temp_char, al // AL is the last 8 bits of the EAX register, what happens here is that AL is then moved into
// the temp_char value, after it has been encrypted; modifying the value before storing it into the EChars array
pop ecx // Restore original register values
pop eax // ""
}
DChars[i] = temp_char; // Store decrypted char
}
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm {
decrypt_17:
push ebp
mov ebp, esp
mov ecx, [ebp + 12] // The base pointer is moved to the location of EKey -- Ekey is moved into ECX
mov eax, [ebp + 8] // Base pointer points to Ekey address
push esi // Push ESI to the top of the stack, ready for storing the EKey value later on in the mov esi, eax line
push ecx // Push ECX to the top of the stack, in this program our ECX register holds the variable temp_char
mov esi, eax // Copy the register (EAX) that the address of Ekey is stored in, into ESI
// Gets EKey
and dword ptr[esi], 0xFF // AND the address in ESI which contains the Ekey with FF in hex
rol byte ptr[esi], 2 // Revert the two rotate right with carry operations
sub byte ptr[esi], 0x01 // The byte ptr implies that the operand size is 8-bits in value; subbing 1 in hex is the opposite of adding
mov ecx, [esi]
pop edx // Get temp_char
x17 : rol al, 1 // Revert the rotate right op
// carry loops back around to the most-significant bit of the value
inc ecx // Here is where I'm having issues with the reversal... I don't know when to stop decrementing
cmp ecx, 0x52
jle x17
mov eax, edx // ***The modifed temp_char value stored in EDX is then moved into the EKey register
sub eax, 0x20
xor eax, 0xAA
pop esi // Restoring the value on top of the stack, in this case the modified temp_char value to the top of the stack ready for the next call
mov ebp, esp // Resetting the first instruction; Base Pointer val
pop ebp // Return original EBP value
ret // Return the encrypted value, stored in EAX/AL to the calling function
}
}
答案 0 :(得分:0)
我尽力发表评论并尽力理解。
很抱歉直言不讳,但编写解码器还不够好,简直就是意外。
我会评论一些事情,但可能有太多东西无法理解......
push eax // Prepare the EAX register to store volatile memory.
push ecx // Prepare the ECX register to store volatile memory.
(1)&#34;堆叠内存&#34;是普通的存储器,但为方便起见,寄存器对ss:esp
指向堆栈的假想&#34;顶部&#34;,它向低地址增长。 IE浏览器。 push eax
可以被视为esp = esp - 4; [esp] = eax;
,将值写入内存,并更新esp
以指向它。 pop
正在撤消此操作,从[esp]
加载值并将esp += 4;
更新为&#34;从堆栈中释放值&#34;。
push ecx // Push ecx to the top of the stack. Stores char
push eax // Stores address of ekey
call encrypt_17 // Calls the encyrption routine below, before jumping back up to the line below
add esp, 8 // Adding 8 to the stack pointer moves the pointer to (somewhere in the stack, I'm unsure where)
不确定为什么他们将char + EChar地址置于堆栈中,当他们根本不使用它们时(encrypt_17
从寄存器中获取值,而不是从堆栈中获取),可能只是为了添加混乱。无论如何,由于两个push
正在使用32位(== 4字节)值,这意味着add esp,8
将&#34;扔掉&#34;两者(再次检查(1)或在调试器中观察),将堆栈恢复到此部分代码之前的状态,然后最终恢复原始eax/ecx
将正常工作。顺便说一句,encrypt_17
确实修改了edx
,它还没有被恢复,因此只有当编译器不需要为C代码保留edx
时,这个内联汇编才能运行(幸运)。
encrypt_17:
push esi
push ecx //temp char t = 116 first time around
mov esi, eax //sets eax to esi, which has a value of '2422272'
存储到堆栈中(此时顶部是返回上面代码的ret
指令)旧esi
,以及要编码的字符(在ecx
中),然后将esi
设置为eax
(esi = EChar address;
),而不是设置为esi。
and dword ptr[esi], 0xFF
ror byte ptr[esi], 1
ror byte ptr[esi], 1 //these two lines set Ekey I(72) to Ekey R(82) (inc by 10?)
add byte ptr[esi], 0x01 //adds 1 to the ekey, changing it to S
这是一种玩笑吗?您真的不愿意阅读英特尔指令参考指南以了解ror
的作用吗? (注释中的值必须是错误的,我不是72,向右旋转72次不是82,也不是十进制,或者是十六进制(不清楚,你正在使用哪一个)。)
mov ecx, [esi] //move location of Ekey (S) to ECX
pop edx //restore original val of edx (which appears to be 116 (temp char, t from 'test')
将修改后的EChar [0]值加载到cl
(高位24位被第一个and dword
归零,因此读取ecx
,但只有低8位是有趣的。然后pop edx
会将存储在堆栈中的最后一个值弹出到edx
。最后的值是原始的ecx
(要加密的字符)。再次参见(1)以实现push/pop
配对寄存器上没有固定,但它取决于push/pop
指令的顺序,从哪个寄存器存储/加载哪个值。通过mov edx,ecx
来执行encrypt_17
,可以实现相同的效果。 ror dl, 1 //dl = t, after this it's set to 58 ':', edx is also set to 58,
的开头。
edx
dl
和58
是相同的注册,当然两者都是edx
。不同之处在于dl
是完整的32位,而dl
是其中最低的8位部分,可以使用ror
别名单独使用。并且edx
仅在低8位部分完成,因此从b0右侧离开的任何位将重新进入ror edx,1
的b7,而不是b31。这将需要dh
(旋转所有32位)。您还可以通过别名dx
单独访问位b8-b15,通过别名edx
单独访问位b0-b15。并且整个rdx
在64b CPU上是 mov eax, edx //eax gets set to 142. which is 'Z' with an arrow above it
add eax, 0x20 //eax gets set to 174, from 154
的低32位部分别名。
eax
首先你说 xor eax, 0xAA //XOR'ing 154 with AA sets it to 4
是142,然后突然是154?当0x20为32时,它清楚为142(142 + 32 = 174)。注意哪些值以六进制格式显示,不要将0x20与20十进制混合。
xor
在这种情况下甚至不确定为什么显示十进制值(并且它是174,而不是154),例如对0xAA
执行0xAE
对0x04
很容易看到特定位,它将如何结束xor
。在十进制中,你不能看到&#34;&#34;&#34;位,您必须先将其转换为二进制/六进制才能在头部进行 pop esi //ECX gets set to 0
ret //value gets returned
计算。
esi
这会恢复旧ecx
,pop
上的任何内容都不会更改。此外,堆栈在返回地址后再次指向ret
(清除所有本地混乱),因此push
将起作用。如果您忘记堆栈上的某些ret
,xor
将使用错误的值作为返回地址,从而导致崩溃。
所以加密主要是多次旋转这些位(无用,因为每获得原始值的第8次旋转,所以只有模数8的旋转有一些效果),有一些加法和xoring,所有这些都可以直接方式反转
有趣的是,只使用EKey的第一个字节,接下来的三个设置为零,其余部分被忽略。所以这是8位密钥强加密... eee ...&#34; strong&#34;。
关于逆转:
1)EKey不反转&#34;,保持计算与加密相同,在EKey中具有相同的值进行解密。
2)向后解密char,从最后一个op(ecx
)等开始......
3)你不需要将ror
计数器增加到未知值,你执行的循环次数与加密次数相同(从[esi]到0),而不是rol
你做xor 0xAA
,这是将加密效果逆转为解密的原因。
所以基本上EKey相关的东西是完整的(以与加密相同的方式完成),结果是旋转次数(加密/解密相同,因为你反转旋转方向来撤消它)。 char本身的操作按顺序和操作逻辑颠倒过来。 IE浏览器。 xor 0xAA
反转ror
(是的,相同的一个),rol
由add
,sub
反转{{1}}(或负值) )等等。