汇编插入语句 ■汇编语言编程很困难.求两个数的和比较容易,但对于 输入输出等非常困难. ■要了解处理器结构和操作系统,很复杂 ■汇编插入语句可以在熟悉的环境里进行 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 1 ■汇编语言编程很困难. 求两个数的和比较容易,但对于 输入输出等非常困难. ■要了解处理器结构和操作系统,很复杂 ■ 汇编插入语句可以在熟悉的环境里进行. 汇编插入语句
最简单的汇编插入语句形式(求两个数之和) main() int a=1: /声明变量a并赋值为1 int b=2; /1声明变量b并赋值为2 int c; /声明变量c,不对它进行初始化 //汇编插入语句的开始位置 -asm( MOV EAX,a 将变量a的值加载到EAX寄存器 MOV EBX,b:将变量b的值加载到EBX寄存器 ADD EAX, EBX;EAX与EBX相加,并将结果写入EAX MOC C, EAX将EAX的值传送到变量C /汇编插入语句的结束位置 //用常用的c语言函数printf输出 //变量c的值 printf("a+b=8x+号x-号xn",a,b,c): 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 2
方法:直接在内存中搜索用户输入的密码 ■由于各种复杂的原因,密码不可能会放在很容易找到的 地方,同时程序中也有非常多的字特串都很像密码串。 ■想法: 搜索原始密码很难,搜索用户输入的密码应该简单。 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 3 ■由于各种复杂的原因, 密码不可能会放在很容易找到的 地方, 同时程序中也有非常多的字符串都很像密码串。 ■想法: 搜索原始密码很难,搜索用户输入的密码应该简单。 方法1: 直接在内存中搜索用户输入的密码
方法:直接在内存中搜索用户输入的密码 ■工作过程: idag 运行程序。 输入“KPNC Kaspersky" 转idag调试方式,搜索XPNC Kaspersky字待 串。可找出多个位置,分析选择可能性最大的一个。 在相应位置处004295E0中设置断点 然后重新启动idag运行。 断点设置在检测调用语句之后的指令上。 退出匹配的进程/修正丁MP指令以及. 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 4 ■工作过程: idag 运行 程序。 输入“ KPNC Kaspersky” 转idag 调试方式, 搜索KPNC Kaspersky 字符 串。可找出多个位置,分析选择可能性最大的一个。 在相应位置处004295E0中设置断点 然后重新启动idag 运行。 断点设置在检测调用语句之后的指令上。 退出匹配的进程/修正JMP指令以及…… 方法1: 直接在内存中搜索用户输入的密码
输入密码的程序 for(;; { printf("Enter password:") fgets(&buff[O],PASSWORD_SIZE,stdin): if(strcmp(&buff[O],PASSWORD)) /"中斥"密码不匹配 printf("Wrong password\n"); else break; if (++count>3)return-1; 2022/11/8 Chen Kaiming Copyright 2007 5
2022/11/8 Chen Kaiming Copyright 2007 5 for( ; ; ) { printf("Enter password: "); fgets(&buff[0] , PASSWORD_SIZE, stdin); if (strcmp( &buff[0] , PASSWORD)) // "申斥"密码不匹配 printf("Wrong password\n"); else break; if (++count>3) return -1; } 输入密码的程序
输入密码程序的分析 ■分析: 用户提供的密码被放在buf仟缓冲区并与参照密码比 较,如果不匹配,那么,需要从用户那里再次请求提供密 码. ■第二次输入前不清除buff. 依次类推,到达接受Wrong password执行分支,使用 调试器,进行搜索,就会找到. 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 6 ■分析: 用户提供的密码被放在 buff 缓冲区 并与参照密码比 较,如果不匹配, 那么需要从用户那里再次请求提供密 码. ■第二次输入前不清除 buff. 依次类推, 到达接受Wrong password 执行分支, 使用 调试器, 进行搜索, 就会找到. 输入密码程序的分析
实验和验证 执行list1p7.exe 输入密码:chenkaiming ●00425A30 iob dd offset bufin ●00425A30 "chenkaiming \n\n" 00425A38 dd offset_bufin "chenkaiming\n\n" (00425A38不合题意,舍去) 2022/11/8 Chen Kaiming Copyright 2007 7
2022/11/8 Chen Kaiming Copyright 2007 7 实验和验证 执行 list1_p7.exe 输入密码: chenkaiming ⚫ 00425A30 _iob dd offset _bufin ⚫ 00425A30 "chenkaiming\n\n" ⚫ 00425A38 dd offset _bufin "chenkaiming\n\n" ( 00425A38 不合题意, 舍去)
■搜索立即数 0x00425A30得两处: 00401042 push offset_iob 00401047 push 64h /最大密码长度 00401049 lea eax,[ebp+var_68]/密码缓冲区指针 0040104C push eax 0040104D call fgets 00401052 add esp,OCh //弹出三个参数 00401055 push "myGOODpassword\n" 0040105A lea ecx,[ebp+var_68] 0040105D push ecx 0040105E call strcmp 00401063 add esp,8 00401066 test eax,eax 00401068 jz short loc_401079 0040106A push offset@;"Wrong password\n" 0040106F call printf 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 8 ■搜索立即数 0x00425A30 得两处: 00401042 push offset _iob 00401047 push 64h //最大密码长度 00401049 lea eax, [ebp+var_68] // 密码缓冲区指针 0040104C push eax 0040104D call fgets 00401052 add esp, 0Ch //弹出三个参数 00401055 push "myGOODpassword\n" 0040105A lea ecx, [ebp+var_68] 0040105D push ecx 0040105E call strcmp 00401063 add esp, 8 00401066 test eax, eax 00401068 jz short loc_401079 0040106A push offset@ ; "Wrong password\n" 0040106F call printf
方法2在密码输入函数上没置断点 void CCrackme_01Dlg::OnOk( { char buff[PASSWORD_SIZE]; CEdit m_password; m_password.GetWindowTextA(&buff[O] PASSWORD_SIZE); if(strcmp(&buff[O],PASSWORD)) { printf("Wrong Password"); m_password.SetSel(O,-1,0) return; } else printf("Password OK"): CDialog::OnOK(); } 2022/11/8 Chen Kaiming Copyright 2007
2022/11/8 Chen Kaiming Copyright 2007 9 方法2 在密码输入函数上设置断点 void CCrackme_01Dlg::OnOk() { char buff[PASSWORD_SIZE]; CEdit m_password; m_password.GetWindowTextA(&buff[0], PASSWORD_SIZE); if (strcmp(&buff[0], PASSWORD)) { printf("Wrong Password"); m_password.SetSel(0,-1,0); return; } else { printf("Password OK"); } CDialog::OnOK(); }
方法2在密码输入函数上没置断点 void CCrackme_01Dlg::OnOk( { char buff[PASSWORD_SIZE]: CEdit m_password; m_password.GetWindowTextA(&buff[O] PASSWORD_SIZE): if(strcmp(&buff[O],PASSWORD)) { printf("Wrong Password"); m_password.SetSel(0,-1,0): return; } else printf("Password OK"): CDialog::OnOK(); } 2022/11/8 Chen Kaiming Copyright 2007 10
2022/11/8 Chen Kaiming Copyright 2007 10 方法2 在密码输入函数上设置断点 void CCrackme_01Dlg::OnOk() { char buff[PASSWORD_SIZE]; CEdit m_password; m_password.GetWindowTextA(&buff[0], PASSWORD_SIZE); if (strcmp(&buff[0], PASSWORD)) { printf("Wrong Password"); m_password.SetSel(0,-1,0); return; } else { printf("Password OK"); } CDialog::OnOK(); }