如何暴力破坏有损常规?

问题描述

我想知道是否存在任何通过蛮力逆转AND例程的标准方法。 例如,我有以下转换:

MOV(eax,0x5b3e0be0)  <- Here we move 0x5b3e0be0 to EDX.
MOV(edx,eax)  # Here we copy 0x5b3e0be0 to EAX as well.
SHL(edx,0x7)  # Bitshift 0x5b3e0be0 with 0x7 which results in 0x9f05f000
AND(edx,0x9d2c5680)  # AND 0x9f05f000 with 0x9d2c5680 which results in 0x9d045000
XOR(edx,eax)  # XOR 0x9d045000 with original value 0x5b3e0be0 which results in 0xc63a5be0

我的问题是如何强行使用和反转该例程(即将0xc63a5be0转换回0x5b3e0be0)

我有一个想法(不起作用)是使用PeachPy实现的:

#Input values
MOV(esi,0xffffffff) < Initial value to AND with,which will be decreased by 1 in a loop.
MOV(cl,0x1) < Initial value to SHR with which will be increased by 1 until 0x1f.
MOV(eax,0xc63a5be0) < Target result which I'm looking to get using the below loop.
MOV(edx,0x5b3e0be0) < Input value which will be transformed.

sub_esi = peachpy.x86_64.Label()
with loop:
    #End the loop if ESI = 0x0
    TEST(esi,esi)
    JZ(loop.end)
    #Test the routine and check if it matches end result.
    MOV(ebx,eax)
    SHR(ebx,cl)
    TEST(ebx,ebx)
    JZ(sub_esi)
    AND(ebx,esi)
    XOR(ebx,eax)
    CMP(ebx,edx)
    JZ(loop.end)
    #Add to the CL register which is used for SHR.
    #Also check if we've reached the last potential value of CL which is 0x1f
    ADD(cl,0x1)
    CMP(cl,0x1f)
    JNZ(loop.begin)

    #Decrement ESI by 1,reset CL and restart routine.
    peachpy.x86_64.LABEL(sub_esi)
    SUB(esi,0x1)
    MOV(cl,0x1)
    JMP(loop.begin)

#The ESI result here will either be 0x0 or a valid value to AND with and get the necessary result.
RETURN(esi)

也许是您可以推荐的文章或书籍?

解决方法

这不是有损的,最后的操作是XOR。
整个例程可以用C建模为

#define K 0x9d2c5680
uint32_t hash(uint32_t num)
{
  return num ^ ( (num << 7) & K);
}

现在,如果我们有两个位 x y 以及操作 x XOR y ,当 y 为零,结果为 x
因此,给定两个数字 n1 n2 并考虑它们的XOR,在 n2 中与零配对的位或 n1 >会变成结果未更改(其他将被翻转)。

因此,在考虑num ^ ( (num << 7) & K)时,我们可以将num标识为 n1 ,将(num << 7) & K标识为 n2
由于 n2 是AND,因此我们可以说它必须至少具有与 K 相同的零位。
这意味着num的每个与常量 K 中的零位相对应的位都将使其不变为结果。
因此,通过从结果中提取这些位,我们已经有了部分逆函数:

/*hash & ~K extracts the bits of hash that pair with a zero bit in K*/
partial_num = hash & ~K

从技术上讲,num << 7因子还将在AND结果中引入其他零。我们肯定知道最低的7位必须为零。
但是 K 已经具有最低的7位零,因此我们无法利用此信息。
因此,我们在这里只使用 K ,但是如果其值不同,则需要考虑AND(实际上,这意味着将 K 的低7位清零>)。

这给我们留下了13个未知的位(对应于 K 中设置的位)。 如果我们暂时忘记AND,我们将拥有x ^ (x << 7)的含义

h i = num i 表示 i ,范围从0到6(含)
h i = num i ^ num i-7 for i 从7到31(含)
(第一行是由于右侧的低7位为零)

从这里开始,从h 7 开始,然后我们可以检索num 7 作为h 7 ^ num 0 = h 7 ^ h 0
从第7位开始,等式不起作用,我们需要使用num k (对于合适的 k ),但是幸运的是,我们已经在上一步中计算了其值(这就是为什么我们从低到高开始)。

AND对此所做的只是将索引 i 所运行的值限制在特定范围内,特别是仅将 K 中设置的位限制为该值。

所以要填写剩余的十三位,必须要做的:

part_num 7 = h 7 ^ part_num 0
part_num 9 = h 9 ^ part_num 2
part_num 12 = h 12 ^ part_num 5
...
part_num 31 = h 31 ^ part_num 24

请注意,我们利用了part_num 0..6 = h 0..6

这是一个C函数,可以将函数取反:

#include <stdio.h>
#include <stdint.h>


#define BIT(i,hash,result) ( (((result >> i) ^ (hash >> (i+7))) & 0x1) << (i+7) )
#define K 0x9d2c5680

uint32_t base_candidate(uint32_t hash)
{
  uint32_t result = hash & ~K;

  result |= BIT(0,result);
  result |= BIT(2,result);
  result |= BIT(3,result);
  result |= BIT(5,result);
  result |= BIT(7,result);
  result |= BIT(11,result);
  result |= BIT(12,result);
  result |= BIT(14,result);
  result |= BIT(17,result);
  result |= BIT(19,result);
  result |= BIT(20,result);
  result |= BIT(21,result);
  result |= BIT(24,result);

  return result;
}

uint32_t hash(uint32_t num)
{
  return num ^ ( (num << 7) & K);
}



int main()
{

  uint32_t tester = 0x5b3e0be0;
  uint32_t candidate = base_candidate(hash(tester));

  printf("candidate: %x,tester %x\n",candidate,tester);
  
  return 0;

}
,

由于最初的问题是如何“蛮力”而不是解决,所以我最终想到了一些同样有效的方法。显然,根据输入,它容易出错(可能会超过1个结果)。

python -m pip install wheel                        # only first time
python -m pip install wheel_file.whl               # for each library you want to install

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...