Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/89.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gdb-查找密码_Gdb - Fatal编程技术网

gdb-查找密码

gdb-查找密码,gdb,Gdb,假设我有以下功能: void personalData() { char password[30]; puts("Please enter your password"); fgets(password, 6, stdin); if(correctPassword(password) != 0) { puts("Try again later !"); } else { puts("Hello master");

假设我有以下功能:

void personalData()
{
    char password[30];
    puts("Please enter your password");
    fgets(password, 6, stdin);

    if(correctPassword(password) != 0) {
        puts("Try again later !");
    }
    else {
        puts("Hello master");
    }
}

int correctPassword(char password[5])
{
    int i = 0;
    char desiredPassword[5] = {0x12, 0x13, 0x14, 0x15, 0x16};
    char hash[5] = {0x22, 0x23, 0x24, 0x25, 0x26};

    for(i = 0; i < 5; ++i) {
        password[i] ^= hash[i];
    }
    return strncmp(password, desiredPassword, 5);
}

int main() {
    personalData();
    return 0;
}
void personalData()
{
字符密码[30];
放入(“请输入您的密码”);
fgets(密码,6,标准输入);
如果(更正密码(密码)!=0){
放置(“稍后再试!”);
}
否则{
放置(“你好,主人”);
}
}
int correctPassword(字符密码[5])
{
int i=0;
字符desiredPassword[5]={0x12、0x13、0x14、0x15、0x16};
字符哈希[5]={0x22、0x23、0x24、0x25、0x26};
对于(i=0;i<5;++i){
密码[i]^=hash[i];
}
返回strncmp(密码,desiredPassword,5);
}
int main(){
个人数据();
返回0;
}
我的目标是使用gdb查找我应该为
password
选择什么密码,以便函数personalData打印Hello master。我试着使用断点,每个部分都有许多伪装,但我不知道在哪里可以找到实际的结果。我也试着在strncmp中查找,但没有结果。
我不应该更改源代码。

由于哈希数组可能未知(但可以从GDB访问),您需要将密码设置为
hash[n]^desiredPassword[n]
。由于xor的反函数是xor,因此结果应该是所需的密码

以下是演示代码:

 #include <stdio.h>

char hash[] =  {0x23, 0x45, 0x55, 0xbb, 0xdd};    /* Some unknown values */


void personalData()
{
    char password[30];

    puts("Please enter your password");
    fgets(password, 6, stdin);


    if(correctPassword(password) != 0) {
        puts("Try again later !");
    }
    else {
        puts("Hello master");
    }
}

int correctPassword(char password[5])
{
    int i = 0;
    char desiredPassword[5] = {0x12, 0x13, 0x14, 0x15, 0x16};
    for(i = 0; i < 5; ++i) {
        password[i] ^= hash[i];
    }
    return strncmp(password, desiredPassword, 5);
}


int main()
{
    personalData();
}
一旦进入gdb控制台:

(gdb) b correctPassword 
Breakpoint 1 at 0x4006b9: file find_passwd.c, line 32.
(gdb) r
Starting program: /home/xxx/workspace/c/xx/a.out 
Please enter your password
garbagePasswd

Breakpoint 1, correctPassword
32      int i = 0;
(gdb) n
33      char desiredPassword[5] = {0x12, 0x13, 0x14, 0x15, 0x16};
(gdb) 
34      for(i = 0; i < 5; ++i) {
(gdb) set password[0] = hash[0] ^ desiredPassword[0]
(gdb) set password[1] = hash[1] ^ desiredPassword[1]
(gdb) set password[2] = hash[2] ^ desiredPassword[2]
(gdb) set password[3] = hash[3] ^ desiredPassword[3]
(gdb) set password[4] = hash[4] ^ desiredPassword[4]
(gdb) c
Continuing.
Hello master
[Inferior 1 (process 19557) exited normally]
(gdb)b更正密码
断点1位于0x4006b9:文件find_passwd.c,第32行。
(gdb)r
启动程序:/home/xxx/workspace/c/xx/a.out
请输入您的密码
垃圾袋
断点1,更正密码
32 int i=0;
(gdb)n
33字符所需密码[5]={0x12、0x13、0x14、0x15、0x16};
(gdb)
34表示(i=0;i<5;++i){
(gdb)设置密码[0]=哈希[0]^desiredPassword[0]
(gdb)设置密码[1]=哈希[1]^desiredPassword[1]
(gdb)设置密码[2]=哈希[2]^desiredPassword[2]
(gdb)设置密码[3]=哈希[3]^desiredPassword[3]
(gdb)设置密码[4]=哈希[4]^desiredPassword[4]
(gdb)c
持续的。
你好,主人
[次品1(过程19557)正常退出]
我的目标是使用gdb找到我应该为密码选择的密码,以便函数personalData打印Hello master

您没有说明正在使用的平台。让我们假设Linux/x86_64。平台很重要,因为调用约定取决于平台。这里的答案可以很容易地针对不同的平台进行调整

让我们考虑优化二进制的情况(通常更难)。拆解<代码> PuxalDATa<代码>显示:

   0x000000000040074d <+45>:    callq  0x400560 <fgets@plt>
   0x0000000000400752 <+50>:    xor    %eax,%eax
   0x0000000000400754 <+52>:    mov    %rsp,%rdi
   0x0000000000400757 <+55>:    callq  0x400680 <correctPassword>
   0x000000000040075c <+60>:    test   %eax,%eax
   0x000000000040075e <+62>:    jne    0x400780 <personalData+96>
正在打印一些输出。如果
correctPassword
返回
0
且未进行跳转,将打印什么

(gdb) x/s 0x400851
0x400851:   "Hello master"
因此,我们的目标是使
correctPassword
返回0。让我们看看它的反汇编:

(gdb) disas correctPassword
....
  0x0000000000400673 <+99>: callq  0x4004c0 <strncmp@plt>
  0x0000000000400678 <+104>:    add    $0x28,%rsp
  0x000000000040067c <+108>:    retq
上面我输入了9个字符的密码,这只是我的初步猜测

Breakpoint 1, __strncmp_ssse3 () at ../sysdeps/x86_64/multiarch/../strcmp.S:174
174 ../sysdeps/x86_64/multiarch/../strcmp.S: No such file or directory.
我碰巧安装了GLIBC调试符号,实际上可以检查GLIBC源代码和源代码级参数,但您可能没有这样的特权,因此我将使用
Linux/x86_64
。从中,您可以看到
strncmp
的3个参数在
RDI
RSI
RDX
注册表中传递他们的价值观是什么

(gdb) p/x $rdi
$1 = 0x7fffffffdd50
(gdb) p/x $rsi
$2 = 0x7fffffffdd20
(gdb) p/x $rdx
$3 = 0x5
好的,所以只比较密码的前5个字符,之后的任何字符都将被忽略

比较的字符串是什么

(gdb) x/s $rdi
0x7fffffffdd50: "CBEDG"
(gdb) x/s $rsi
0x7fffffffdd20: "\022\023\024\025\026"
嗯,这两个字符串都不像我们的“aaa…”密码。让我们尝试另一个密码:

(gdb) run
Starting program: /tmp/a.out
Please enter your password
bbbbb

Breakpoint 1, __strncmp_ssse3 () at ../sysdeps/x86_64/multiarch/../strcmp.S:174
174 ../sysdeps/x86_64/multiarch/../strcmp.S: No such file or directory.
(gdb) x/s $rdi
0x7fffffffdd50: "@AFGD"
(gdb) x/s $rsi
0x7fffffffdd20: "\022\023\024\025\026"
我们现在可以立即看到,
$rsi
序列没有改变,并且可以假定
“\022\023\024\025\026”
是预期的密码

我们还看到第一个
a
被转换成
C
,而
b
被转换成
@
。从这里我们可以选择两种方法之一:我们可以尝试更多的字符,猜测输入->模糊密码算法是什么,或者我们可以进一步查看反汇编并简单地“读取”它

分解显示:

   0x0000000000400622 <+18>:    movb   $0x12,(%rsp)
...
   0x000000000040062a <+26>:    movb   $0x13,0x1(%rsp)
   0x000000000040062f <+31>:    movb   $0x14,0x2(%rsp)
   0x0000000000400634 <+36>:    movb   $0x15,0x3(%rsp)
   0x0000000000400639 <+41>:    movb   $0x16,0x4(%rsp)
   0x000000000040063e <+46>:    movb   $0x22,0x10(%rsp)
   0x0000000000400643 <+51>:    movb   $0x23,0x11(%rsp)
   0x0000000000400648 <+56>:    movb   $0x24,0x12(%rsp)
   0x000000000040064d <+61>:    movb   $0x25,0x13(%rsp)
   0x0000000000400652 <+66>:    movb   $0x26,0x14(%rsp)
这是一个固定行程计数为5的循环,在循环中,我们从一个缓冲区加载一个字符,然后用另一个缓冲区的字符加载该值。密码的第一个字符被
XOR
0x22
加密的几率有多大

(gdb) p/c 'a' ^ 0x22
$5 = 67 'C'
(gdb) p/o 0x12
$6 = 022
(gdb) p/c 'b' ^ 0x22
$7 = 64 '@'
这看起来很有希望!(当然,您可以通过在适当的指令上设置断点,在模糊处理过程之前和期间确认各种缓冲区的内容)

作为对我们猜测的最后确认,最后一个字符被
XOR
0x26
合并

(gdb) p/c 'a' ^ 0x26
$8 = 71 'G'           # matches last char of 'aaa...' guess
(gdb) p/c 'b' ^ 0x26
$9 = 68 'D'           # matches last char of 'bbb...' guess
最后,为了构造正确的密码,我们需要获取“目标”字符串,并对其执行相同的
XOR
s序列:

(gdb) p/c 022 ^ 0x22
$10 = 48 '0'
(gdb) p/c 023 ^ 0x23
$11 = 48 '0'
... etc.
因此,正确的密码是
00000

(gdb) disable
(gdb) run
Starting program: /tmp/a.out
Please enter your password
00000
Hello master
[Inferior 1 (process 45643) exited normally]

QED.

你的代码不完整--哈希从何而来?@EmployeedRussian抱歉,我忘了复制那段代码。现在它完成了。谢谢,但我应该用gdb来做这件事…这种解决方法与gdb无关。我不想覆盖任何内容…我想用gdbYou j来找到密码的实际值ust需要在异或后打印密码值,类似的操作应该可以
(gdb)p/s*password@5
正好是
0000
(gdb) p/c 'a' ^ 0x22
$5 = 67 'C'
(gdb) p/o 0x12
$6 = 022
(gdb) p/c 'b' ^ 0x22
$7 = 64 '@'
(gdb) p/c 'a' ^ 0x26
$8 = 71 'G'           # matches last char of 'aaa...' guess
(gdb) p/c 'b' ^ 0x26
$9 = 68 'D'           # matches last char of 'bbb...' guess
(gdb) p/c 022 ^ 0x22
$10 = 48 '0'
(gdb) p/c 023 ^ 0x23
$11 = 48 '0'
... etc.
(gdb) disable
(gdb) run
Starting program: /tmp/a.out
Please enter your password
00000
Hello master
[Inferior 1 (process 45643) exited normally]