c 怎样输入y继续执行?求大神看我的代码z x y出什么问题

下面的程序是C的简易计算器。。给我看看输入Y/N的地方为什么输入不了????在机器上运行下吧。。。。
你正在浏览: & >
下面的程序是C的简易计算器。。给我看看输入Y/N的地方为什么输入不了????在机器上运行下吧。。。。
下面的程序是C的简易计算器。。给我看看输入Y/N的地方为什么输入不了????在机器上运行下吧。。。。
}printf(&if(d=='y'):printf(&quot,&a,&c;);/&#39,jian(a,b));case 'switch(c){case '+';scanf(&%f%c%f&;}}相关说明:
谢谢各位大虾了。。。。上面的continue是没用的吧
getchar()printf(&quot,&d);scanf(&%c&;);你是否想继续使用?y/n\n&quot
#include&stdio.h&void main() { float x,y,z; char c...~~~
C语言简单的计算器
用多分支条件判断语句编程设计一个简单的计算器程序。 要求: ① 用户按以下形式...~~~
/* 日 12:43:46 目的:计算器的实现 */ # include &st...~~~
#include &stdio.h& void main() { int a[4],b[4],c[4...~~~
以下是我编的简易计算器程序,基本成功 //4*4键盘检测程序,按下键后相应的代码显示在液晶屏上 //...~~~
/* 日 12:43:46 目的:计算器的实现 */ # include &st...~~~
#include&stdio.h&void main(){float a,b,c;pr...~~~
既然是简单计算器,只需要实现加减乘除,同时每次支持两个操作数和一个操作符... ...~~~
C语言程序设计,做一个简单计算器 24
c语言设计一个...刚写的代码
求大神看一下【c语言吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:555,905贴子:
刚写的代码
求大神看一下收藏
&stdio.h&#include
&stdlib.h&int *max(int *x,int *y,int *z);int main(){int a,b,c,*p;printf("请输入三个数据我们将找最大的那个\n");scanf("%d%d%d",&a,&b,&c);p=max(&a,&b,&c);printf("%d %d %d中最大的数字是%d\n",a,b,c,*p);//结合上一次的指向函数的指针试验一下int (*pf)(int *,int *,int *);pf=p=(*pf)(&a,&b,&c);printf("第二次用指针函数实验结果
%d %d %d中最大的数字是%d\n",a,b,c,*p);system("pause");return 0;}int *max(int *x,int *y,int *z){if(*x&=*y){if(*x&=*z){
//返回的值是指针类型!!!!}else{}}else{if(*y&=*z){
时光IT学院,免费在线直播教学,大牛现场答疑;拒绝纯理论学习,以c/c++/java项目实战为核心.针对c/c++/java零基础学员,快速入门,高薪就业.
登录百度帐号推荐应用"c语言怎么判断是否输入y"的糗事
11173 好笑
你可能感兴趣:
糗事百科为大家收集了很多的c语言怎么判断是否输入y的糗事,各种关于c语言怎么判断是否输入y的爆笑经历、尴尬时刻和开心视频,想持续关注c语言怎么判断是否输入y的糗事就收藏本页吧.
扫码下载糗事百科appc语言菜鸟一只,网上看到的代码。求大神分析。谢谢!!!【c程序吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:9,436贴子:
c语言菜鸟一只,网上看到的代码。求大神分析。谢谢!!!收藏
我刚接触半年,基础薄弱,身边没有大神。请各位简单通俗的说说这个系统涉及到的知识点,谢谢!
C/C++入门教程,针对编程零基础的人群;C/C++公开课,使用C语言编写各种小程序.
#include&stdio.h& #include&string.h& #include&conio.h& #include&stdlib.h& #include&ctype.h& #define STACK_INIT_SIZE 10 #define OK 1 #define TRUE 1 #define FALSE 0 #define ERROR 0struct student /*定义学生类型,用于存放借出的书籍*/ {
char lendbook[10]; }student[1000];struct employ /*定义职工类型*/ {
char employname[15];
char employsex[2]; char employleve[10];
}employ[50];struct book /*定义书的类型*/ {
char bookname[10]; char bookcreat[10];
/*用于借书和还书模块判断一本书是否借出的条件*/ }book[1000];struct car /*借书卡的数据类型*/ {
char studentname[10];
}car[100];huanbook() /*还书函数*/ { FILE *fp,*fp2; /*定义两个文件指针,fp2用于修改数据时设立临时文件用,防止数据遭破坏*/ int i,n;
char lendbook[10]; printf("请你输入你的卡号\n"); scanf("%d",&carnum); fp=fopen("car.txt","r"); /*读取卡号记录*/ for(i=0;fread(&car[i],sizeof(struct car),1,fp)!=0;i++) /*for循环判断卡号是否存在*/ {
if(car[i].carnum==carnum) /*卡号存在,进入下一循环*/
fclose(fp);
printf("请输入你要还的书的名字\n");
scanf("%s",lendbook);
fp=fopen("record.txt","r");
for(i=0;fread(&student[i],sizeof(struct student),1,fp)!=0;i++) /*判断是否借阅了输入的书*/
if(strcmp(student[i].lendbook,lendbook)==0) /*借阅了该书,进入下一循环,否则出错显示*/
fclose(fp);
fp=fopen("record.txt","r");
fp2=fopen("bookl.txt","w");
for(i=0;fread(&student[i],sizeof(struct student),1,fp)!=0;i++)
if(strcmp(student[i].lendbook,lendbook)==0)
/*删除还掉的书的借书记录*/
fwrite(&student[i],sizeof(struct student),1,fp2); /*写入原来没还的书的记录*/
fclose(fp);
fclose(fp2);
fp=fopen("record.txt","w");
fp2=fopen("bookl.txt","r");
for(i=0;fread(&student[i],sizeof(struct student),1,fp2)!=0;i++)
fwrite(&student[i],sizeof(struct student),1,fp); /*将借书记录信息写回*/
fclose(fp);
fclose(fp2);
fopen("bookl.txt","w"); /*清临时文件的记录*/
fclose(fp2);
fp=fopen("book.txt","r");
fp2=fopen("bookl.txt","w");
for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++) /*将书的记录写入临时文件,防止因为修改信息破坏以前的记录*/
book[i].turefalse=1;
fwrite(&book[i],sizeof(struct book),1,fp2); /*将还的书的原来状态设为无人借阅的*/
fwrite(&book[i],sizeof(struct book),1,fp2);
fclose(fp);
fclose(fp2);
fp=fopen("book.txt","w");
fp2=fopen("bookl.txt","r");
for(i=0;fread(&book[i],sizeof(struct book),1,fp2)!=0;i++)
fwrite(&book[i],sizeof(struct book),1,fp); /*将临时文件写回*/
fclose(fp);
fclose(fp2);
fopen("bookl.txt","w"); /*清临时文件*/
fclose(fp2);
printf("还书完毕,按任意键返回\n");
printf("你没有借这样的书,任意键返回\n"); /*出错提示*/
fclose(fp);
} } printf("系统没这样的卡,和管理员联系,按任意键返回\n"); /*出错提示*/ fclose(fp); getch(); }findbook(){ FILE * char bookname[10]; int ture,i; fp=fopen("book.txt","r"); printf("请输入你要查找的书名\n"); scanf("%s",bookname); for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++) {
if(strcmp(bookname,book[i].bookname)==0)
if(book[i].turefalse==1)
printf("这本书的详细资料是:%d %s %s 此书现在无人借阅\n按任意键返回\n",book[i].booknum,book[i].bookname,book[i].bookcreat);
else {printf("这本书已经有人借出\n");fclose(fp);return 0;}
fclose(fp);
return FALSE;
} } printf("没有你要查询的书籍\n"); fclose(fp); return FALSE; }findbook1(){ FILE * char bookcreat[10]; int ture,i; fp=fopen("book.txt","r"); printf("请输入你要查找的作者名\n"); scanf("%s",bookcreat); for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++) {
if(strcmp(bookcreat,book[i].bookcreat)==0)
if(book[i].turefalse==1)
printf("这本书的详细资料是:%d %s %s 此书现在无人借阅\n按任意键返回\n",book[i].booknum,book[i].bookname,book[i].bookcreat);
else {printf("这本书已经有人借出\n");fclose(fp);return 0;}
fclose(fp);
return FALSE;
} } printf("没有你要查询的书籍\n"); fclose(fp); return FALSE; }lendcount() { FILE * int i,n=0; fp=fopen("record.txt","r"); for(i=0;fread(&student[i],sizeof(struct student),1,fp)!=0;i++) {
printf("卡号:%d 借出的书籍:%s \n",student[i].carnum,student[i].lendbook);
n=n+1; } fclose(fp); printf("目前共有%d本书借出\n",n); printf("按任意键\n"); getch(); }chabook() { char ch5; do { printf("---------------欢迎进入图书查询系统!--------------\n"); printf(" 1:&按书名查找&\n"); printf(" 2:&按作者查找&\n"); printf(" 0:&返回&\n"); printf("请输入0--2,其他输入非法!\n"); scanf("%s",&ch5); switch(ch5)
case '1':findbook();getch();
case '2':findbook1();getch();
default:printf("无此操作\n");getch();
} }while(ch5!='0');return FALSE; }
lendbook() { FILE *fp,*fp2; int i,n;
printf("请你输入你的卡号\n"); scanf("%d",&carnum); fp=fopen("car.txt","r"); for(i=0;fread(&car[i],sizeof(struct car),1,fp)!=0;i++) {
if(car[i].carnum==carnum)
fclose(fp);
printf("请输入你要借阅的书的名字\n");
scanf("%s",student[n].lendbook);
fp=fopen("book.txt","r");
for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++)
if(strcmp(book[i].bookname,student[n].lendbook)==0)
if(book[i].turefalse==0) {printf("对不起,此书有人借出,请借其他书\n");fclose(fp);getch();}
fclose(fp);
fp=fopen("record.txt","a+");
student[n].carnum=
fwrite(&student[n],sizeof(struct student),1,fp);
fclose(fp);
fp=fopen("book.txt","r");
fp2=fopen("bookl.txt","w");
for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++)
if(strcmp(book[i].bookname,student[n].lendbook)==0)
book[i].turefalse=0;
fwrite(&book[i],sizeof(struct book),1,fp2);
fwrite(&book[i],sizeof(struct book),1,fp2);
fclose(fp);
fclose(fp2);
fp=fopen("book.txt","w");
fp2=fopen("bookl.txt","r");
for(i=0;fread(&book[i],sizeof(struct book),1,fp2)!=0;i++)
fwrite(&book[i],sizeof(struct book),1,fp);
fclose(fp);
fclose(fp2);
fopen("bookl.txt","w");
fclose(fp2);
printf("借书完毕,按任意键返回\n");
printf("不存在这样的书,任意键返回\n");
fclose(fp);
} } printf("你的卡号不存在,请申请新卡,按任意键返回\n"); fclose(fp); getch(); }carcount() { FILE * int i,n=0; fp=fopen("car.txt","r"); for(i=0;fread(&car[i],sizeof(struct car),1,fp)!=0;i++) {
printf("第%d张卡&卡号:%d 姓名:%s 班级:%d&\n",i+1,car[i].carnum,car[i].studentname,car[i].studentclass);
n=n+1; } fclose(fp); printf("目前共有%d本书\n",n); printf("按任意键\n"); getch(); }delcar() { FILE *fp,*fp2;
fp=fopen("car.txt","r"); fp2=fopen("bookl.txt","w"); printf("请输入你要删除的卡号\n"); printf("如果你输入的卡号存在,系统自动删除该信息!如果不存在,系统不做任何改动\n"); scanf("%d",&carnum); for(i=0;fread(&car[i],sizeof(struct car),1,fp)!=0;i++) {
if(car[i].carnum!=carnum)
fwrite(&car[i],sizeof(struct car),1,fp2);
} } fclose(fp); fclose(fp2); printf("是否真的要删除该卡?删除后该书籍的所有信息将无法恢复《Y/N》\n"); scanf("%s",&choice); if(choice=='y'||choice=='Y') {
fp=fopen("car.txt","w");
fp2=fopen("bookl.txt","r");
for(i=0;fread(&car[i],sizeof(struct car),1,fp2)!=0;i++)
fwrite(&car[i],sizeof(struct car),1,fp);
fclose(fp);
fclose(fp2);
fp2=fopen("bookl.txt","w");
fclose(fp2);
printf("按任意键返回\n");
printf("按任意键返回\n");
} }addcar() { FILE * int i=0; fp=fopen("car.txt","a+"); printf("请你输入卡号\n"); scanf("%d",&car[i].carnum); printf("请你输入学生姓名\n"); scanf("%s",car[i].studentname); printf("请你输入班级\n"); scanf("%d",&car[i].studentclass); fwrite(&car[i],sizeof(struct car),1,fp); fclose(fp); printf("输入完毕,任意键返回\n"); getch(); }changemploy() { FILE *fp,*fp2; char employname[10], fp=fopen("employ.txt","r"); fp2=fopen("bookl.txt","w"); printf("请你输入要修改的职工的名字\n"); scanf("%s",employname); for(i=0;fread(&employ[i],sizeof(struct employ),1,fp)!=0;i++) {
if(strcmp(employ[i].employname,employname)==0)
printf("你所要修改的职工的资料如下,请选择你要修改的内容\n");
printf("&职工号:%d职工名:%s 年龄:%d 性别:%s 学历:%s 工资:%d&\n",employ[i].employnum,employ[i].employname,employ[i].employage,employ[i].employsex,employ[i].employleve,employ[i].employtage);
printf("2:修改职工名\n");
printf("3:修改职工年龄\n");
printf("4:修改职工工资\n");
printf("5:修改职工学历\n");
printf("请输入1-5:");
scanf("%s",&choice);
switch(choice)
printf("请输入新的职工号\n");
scanf("%d",&employ[i].employnum);
fwrite(&employ[i],sizeof(struct employ),1,fp2);
printf("请输入新的职工姓名\n");
scanf("%s",employ[i].employname);
fwrite(&employ[i],sizeof(struct employ),1,fp2);
printf("请输入新的年龄\n");
scanf("%d",&employ[i].employage);
fwrite(&employ[i],sizeof(struct employ),1,fp2);
printf("请输入新的职工工资\n");
scanf("%d",&employ[i].employtage);
fwrite(&employ[i],sizeof(struct employ),1,fp2);
printf("请输入新的职工学历\n");
scanf("%s",employ[i].employleve);
fwrite(&employ[i],sizeof(struct employ),1,fp2);
default:printf("没有这样的操作");
fwrite(&employ[i],sizeof(struct employ),1,fp2); } fclose(fp); fclose(fp2); fp=fopen("employ.txt","w"); fp2=fopen("bookl.txt","r"); for(i=0;fread(&employ[i],sizeof(struct employ),1,fp2)!=0;i++)
fwrite(&employ[i],sizeof(struct employ),1,fp);
} fclose(fp); fclose(fp2); fp2=fopen("bookl.txt","w"); fclose(fp2); printf("按任意键返回\n"); getchar();
}delemploy() { FILE *fp,*fp2;
char employname[10], fp=fopen("employ.txt","r"); fp2=fopen("bookl.txt","w"); printf("请输入你要删除的职工名\n"); printf("如果你输入的职工存在,系统自动删除该信息!如果不存在,系统不做任何改动\n"); scanf("%s",employname); for(i=0;fread(&employ[i],sizeof(struct employ),1,fp)!=0;i++) {
if(strcmp(employname,employ[i].employname)!=0)
fwrite(&employ[i],sizeof(struct employ),1,fp2);
} } fclose(fp); fclose(fp2); printf("是否真的要删除该职工信息?删除后的所有信息将无法恢复《Y/N》\n"); scanf("%s",&choice); if(choice=='y'||choice=='Y') {
fp=fopen("employ.txt","w");
fp2=fopen("bookl.txt","r");
for(i=0;fread(&employ[i],sizeof(struct employ),1,fp2)!=0;i++)
fwrite(&employ[i],sizeof(struct employ),1,fp);
fclose(fp);
fclose(fp2);
fp2=fopen("bookl.txt","w");
fclose(fp2);
printf("按任意键返回\n");
return TRUE; } else { printf("按任意键返回\n"); getch(); return FALSE; } }
employcount() { FILE * int i,n=0; fp=fopen("employ.txt","r"); for(i=0;fread(&employ[i],sizeof(struct employ),1,fp)!=0;i++) {
printf("第%d职工的信息如下:\n&职工号:%d 职工名:%s 年龄:%d 性别:%s 学历:%s 工资:%d&\n",n+1,employ[i].employnum,employ[i].employname,employ[i].employage,employ[i].employsex,employ[i].employleve,employ[i].employtage);
n++; } fclose(fp); printf("目前共有%d个职工\n",n); printf("按任意键返回\n"); }addemploy() { FILE * char choice='y'; int i=1; fp=fopen("employ.txt","a+"); while(choice=='y'||choice=='Y') {
printf("请你输入职工号码\n");
scanf("%d",&employ[i].employnum);
printf("请你输入职工名\n");
scanf("%s",employ[i].employname);
printf("请输入职工年龄\n");
scanf("%d",&employ[i].employage);
printf("请你输入性别\n");
scanf("%s",employ[i].employsex);
printf("请你输入职工的学历水平\n");
scanf("%s",employ[i].employleve);
printf("请输入职工的工资\n");
scanf("%d",&employ[i].employtage);
fwrite(&employ[i],sizeof(struct employ),1,fp);
printf("是否要输入下个职工信息?\n");
scanf("%s",&choice); } printf("按任意键返回\n"); fclose(fp); }addbook(){FILE *int i=0;char choice='y';fp=fopen("book.txt","a+");while(choice=='y'||choice=='Y') {
printf("请你输入第%d本书的序号\n",i+1);
scanf("%d",&book[i].booknum);
printf("请你输入书名\n");
scanf("%s",book[i].bookname);
printf("请你输入书的作者\n");
scanf("%s",book[i].bookcreat);
printf("请设为1或0,1代表书还没人借,0表示书已经借出,设其他值,程序运行时无法得出正常结果\n");
printf("请你设定书的状态\n");
scanf("%d",&book[i].turefalse);
fwrite(&book[i],sizeof(struct book),1,fp);
printf("是否要输入下本书\n");
scanf("%s",&choice); } fclose(fp); }bookcount() { FILE * int i,n=0; fp=fopen("book.txt","r"); for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++) {
if(book[i].booknum!=0&&strlen(book[i].bookname)!=0&&strlen(book[i].bookcreat)!=0)
printf("第%d本书&序号:%d 书名:%s 作者:%s 状态:%d&\n",i+1,book[i].booknum,book[i].bookname,book[i].bookcreat,book[i].turefalse);
} } fclose(fp); printf("目前共有%d本书\n",n); printf("按任意键\n"); }delbook() { FILE *fp,*fp2;
char bookname[10], fp=fopen("book.txt","r"); fp2=fopen("bookl.txt","w"); printf("请输入你要删除的书名\n"); printf("如果你输入的书名存在,系统自动删除该信息!如果不存在,系统不做任何改动\n"); scanf("%s",bookname); for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++) {
if(strcmp(bookname,book[i].bookname)!=0)
fwrite(&book[i],sizeof(struct book),1,fp2);
} } fclose(fp); fclose(fp2); printf("是否真的要删除该书籍?删除后该书籍的所有信息将无法恢复《Y/N》\n"); scanf("%s",&choice); if(choice=='y'||choice=='Y') {
fp=fopen("book.txt","w");
fp2=fopen("bookl.txt","r");
for(i=0;fread(&book[i],sizeof(struct book),1,fp2)!=0;i++)
fwrite(&book[i],sizeof(struct book),1,fp);
fclose(fp);
fclose(fp2);
fp2=fopen("bookl.txt","w");
fclose(fp2);
printf("按任意键返回\n");
printf("按任意键返回\n");
} }changebook() { FILE *fp,*fp2; char bookname[10],
fp=fopen("book.txt","r"); fp2=fopen("bookl.txt","w"); printf("请你输入要修改的书籍的书字\n"); scanf("%s",bookname); for(i=0;fread(&book[i],sizeof(struct book),1,fp)!=0;i++) {
if(strcmp(book[i].bookname,bookname)==0)
printf("你所要修改的书的资料如下,请选择你要修改的内容\n");
printf("序号:〈%d〉 书名:〈%s〉 作者:〈%s〉 \n",book[i].booknum,book[i].bookname,book[i].bookcreat);
printf("1:修改书的序号\n");
printf("2:修改书名\n");
printf("3:修改作者\n");
printf("请输入1-3:");
scanf("%s",&choice);
switch(choice)
printf("请输入新的序号\n");
scanf("%d",&book[i].booknum);
fwrite(&book[i],sizeof(struct book),1,fp2);
printf("请输入新的书名\n");
scanf("%s",book[i].bookname);
fwrite(&book[i],sizeof(struct book),1,fp2);
printf("请输入新的作者\n");
scanf("%s",book[i].bookcreat);
fwrite(&book[i],sizeof(struct book),1,fp2);
defaut:printf("没有这样的操作");
fwrite(&book[i],sizeof(struct book),1,fp2); } fclose(fp); fclose(fp2); fp=fopen("book.txt","w"); fp2=fopen("bookl.txt","r"); for(i=0;fread(&book[i],sizeof(struct book),1,fp2)!=0;i++) {
fwrite(&book[i],sizeof(struct book),1,fp); } fclose(fp2); fp2=fopen("bookl.txt","w"); fclose(fp2); printf("按任意键返回\n"); getchar();
} main() { char ch1,ch2,ch3,ch4,ch5; do{
//doxunhuan1
printf("\t\t请你选择操作类型:\n");
printf(" 1:&查阅图书&\n");
printf(" 2:&借阅图书&\n");
printf(" 3:&管理系统&\n");
printf(" 4:&还书&\n");
printf(" 0:&退出&\n");
printf("请输入0--4\n");
scanf("%s",&ch1);
switch(ch1)
case '1':chabook();
case '2':lendbook();;
case '3':{ //case3
{ //doxunhuan2
printf("---------------欢迎进入管理系统!--------------\n");
printf(" 1:&增加图书&\n");
printf(" 2:&删除图书&\n");
printf(" 3:&修改图书资料&\n");
printf(" 4:&书籍统计&\n");
printf(" 5:&职工管理系统&\n");
printf(" 6:&学生管理系统&\n");
printf(" 0:&返回&\n");
printf("请输入0--6,其他输入非法!\n");
scanf("%s",&ch2);
switch(ch2)
case '1':addbook();
case '2':delbook();
case '3':changebook();
case '4':bookcount();getch();
case '5':{
{ //doxunhuan3
printf("---------------欢迎进入职工管理系统!--------------\n");
printf(" 1:&增加员工&\n");
printf(" 2:&删除员工&\n");
printf(" 3:&修改员工资料&\n");
printf(" 4:&员工统计&\n");
printf(" 0:&返回&\n");
printf("请输入0--4,其他输入非法!\n");
scanf("%s",&ch3);
switch(ch3)
case '1':addemploy();getch();
case '2':delemploy();
case '3':changemploy();
case '4':employcount();getch();
default:printf("无此操作\n");getch(); } }//doxunhuan3
while(ch3!='0');
case '6':{
//case6do { //doxunhuan4printf("---------------欢迎进入学生管理系统!--------------\n"); printf(" 1:&申请新卡&\n"); printf(" 2:&删除卡号&\n"); printf(" 3:&借书统计&\n"); printf(" 4:&卡号统计&\n"); printf(" 0:&返回&\n"); printf("请输入0--4,其他输入非法!\n"); scanf("%s",&ch4); switch(ch4) { case '1':addcar(); case '2':delcar(); case '3':lendcount(); case '4':carcount(); case '0': default:printf("无此操作\n");getch(); } }//doxunhuan4while(ch4!='0');
}//case6 case '0': default:printf("无此操作\n");getch(); } }//doxunhuan2
while(ch2!='0');
}//case3 case '4':huanbook(); case '0': default:printf("无此操作\n");getch(); } }//doxunhuan1while(ch1!='0'); }
登录百度帐号推荐应用C语言代码逆向的实战十篇(原创) - 『脱壳破解区』
- 吾爱破解 - LCG - LSG |安卓破解|病毒分析|破解软件|
后使用快捷导航没有帐号?
只需一步,快速开始
请完成以下验证码
请完成以下验证码
查看: 10553|回复: 28
C语言代码逆向的实战十篇(原创)
阅读权限10
以前一直仰慕会找0day,的大牛,便开始学习反汇编,现在稍微接触破解,发现说教程的人似乎对反汇编也不是那么的熟悉,我认为算法分析就应该是将整个换算的流程翻译成自己能认识的语言,至少了然于心吧,而不是来到一个call,eax返回了一个注册码的地址,便注释成“获取注册码的函数”,这又何来的分析呢。于是把前些天做的反汇编笔记发出来分享下。一共十篇,开始是debug版,后来是release的。
白痴的CRACKME和白痴的反汇编分析MFC写的垃圾CRACKME
void CCrackMeDlg::OnButton1()
MessageBox(&flag!!!&);
CString s1;
int c=IDC_EDIT1;
h1=GetDlgItem(IDC_EDIT1);
&&h1-&GetWindowText(s1);
&&a=s1.GetBuffer(6);
&&r=strcmp(a,&123456&);
&&if(r==0)
& &MessageBox(&yes&);
& &MessageBox(&no&);
OD反出来的代码
0040147D& &&&90& && && && & NOP
0040147E& &&&90& && && && & NOP
0040147F& &&&90& && && && & NOP
& &. 6A FF& && && & PUSH -1
& &. 68 581A4000& & PUSH CrackMe.00401A58& && && && && && &&&;&&SE handler installation
& &. 64:A1
MOV EAX,DWORD PTR FS:[0]
0040148D& &. 50& && && && & PUSH EAX
0040148E& &. 64:&MOV DWORD PTR FS:[0],ESP
& &. 51& && && && & PUSH ECX
& &. 57& && && && & PUSH EDI
& &. 6A 00& && && & PUSH 0
& &. 6A 00& && && & PUSH 0
0040149B& &. 8BF9& && && &&&MOV EDI,ECX
0040149D& &. 68 & & PUSH CrackMe.& && && && && && &&&;&&ASCII &flag!!!&(我特意在这里弹个信息框,我为了提示自己按钮事件的代码是从这里开始的!)
& &. E8 E3020000& & CALL &JMP.&MFC42.#4224&& && && && && && &;&&MessageBox(&flag!!!&);
& &. 8D4C24 04& && &LEA ECX,DWORD PTR SS:[ESP+4]
004014AB& &. E8 AA020000& & CALL &JMP.&MFC42.#540&
& &. 68 E8030000& & PUSH 3E8& && && && && && && && && && && &;&&push 编辑框ID
& &. 8BCF& && && &&&MOV ECX,EDI
& &. C0&MOV DWORD PTR SS:[ESP+14],0
004014BF& &. E8 C0020000& & CALL &JMP.&MFC42.#3092&& && && && && && &;&&h1=GetDlgItem(IDC_EDIT1);//取得编辑框句柄
& &. 85C0& && && &&&TEST EAX,EAX
& &. 74 68& && && & JE SHORT CrackMe.& && && && && & ;&&如果h1为0则跳到
& &. 53& && && && & PUSH EBX& && && && && && && && && && && &;&&h1不为0就从这里开始往下走
& &. 8D4C24 08& && &LEA ECX,DWORD PTR SS:[ESP+8]& && && && & ;&&将一个局部变量给ecx以便把ecx压入堆栈
004014CD& &. 56& && && && & PUSH ESI
004014CE& &. 51& && && && & PUSH ECX
004014CF& &. 8BC8& && && &&&MOV ECX,EAX
& &. E8 A8020000& & CALL &JMP.&MFC42.#3874&& && && && && && &;&&h1-&GetWindowText(s1);//得到字符串
& &. 6A 06& && && & PUSH 6
& &. 8D4C24 10& && &LEA ECX,DWORD PTR SS:[ESP+10]
004014DC& &. E8 & & CALL &JMP.&MFC42.#2915&& && && && && && &;&&a=s1.GetBuffer(6);//转为char
& &. BE & & MOV ESI,CrackMe.& && && && && &&&;&&ASCII &123456&
& && 8A10& && && &&&MOV DL,BYTE PTR DS:[EAX]& && && && && &&&;&&从这里开始应该是把C的库函数strcmp给弄过来了
& &. 8A1E& && && &&&MOV BL,BYTE PTR DS:[ESI]& && && && && &&&;&&有时间看看人家的strcmp是怎么实现的!
004014EA& &. 8ACA& && && &&&MOV CL,DL
004014EC& &. 3AD3& && && &&&CMP DL,BL
004014EE& &. 75 1E& && && & JNZ SHORT CrackMe.0040150E
& &. 84C9& && && &&&TEST CL,CL
& &. 74 16& && && & JE SHORT CrackMe.0040150A
& &. 8A50 01& && &&&MOV DL,BYTE PTR DS:[EAX+1]
& &. 8A5E 01& && &&&MOV BL,BYTE PTR DS:[ESI+1]
004014FA& &. 8ACA& && && &&&MOV CL,DL
004014FC& &. 3AD3& && && &&&CMP DL,BL
004014FE& &. 75 0E& && && & JNZ SHORT CrackMe.0040150E
& &. 83C0 02& && &&&ADD EAX,2
& &. 83C6 02& && &&&ADD ESI,2
& &. 84C9& && && &&&TEST CL,CL
& &.^75 DC& && && & JNZ SHORT CrackMe.
0040150A& && 33C0& && && &&&XOR EAX,EAX
0040150C& &. EB 05& && && & JMP SHORT CrackMe.
0040150E& && 1BC0& && && &&&SBB EAX,EAX
& &. 83D8 FF& && &&&SBB EAX,-1
& && 5E& && && && & POP ESI
& &. 5B& && && && & POP EBX
& &. 85C0& && && &&&TEST EAX,EAX
& &. 6A 00& && && & PUSH 0
& &. 6A 00& && && & PUSH 0
0040151B& &. 75 07& && && & JNZ SHORT CrackMe.& && && && && &;&&上面应该是把C的库函数strcmp给弄过来了,在这里(不为0跳到no)
0040151D& &. 68 & & PUSH CrackMe.& && && && && && &&&;&&ASCII &yes&
& &. EB 05& && && & JMP SHORT CrackMe.
& && 68 & & PUSH CrackMe.& && && && && && &&&;&&ASCII &no&
& && 8BCF& && && &&&MOV ECX,EDI
0040152B& &. E8 5A020000& & CALL &JMP.&MFC42.#4224&& && && && && && &;&&真会省的!只用了一个MessageBox!要知道我们用C++是写了两次啊!
& && 8D4C24 04& && &LEA ECX,DWORD PTR SS:[ESP+4]& && && && & ;&&在遥远的上面的JE跳到这里来,然后就不关我们事啦
& &. C74424 10 FFFF&MOV DWORD PTR SS:[ESP+10],-1
0040153C& &. E8 0D020000& & CALL &JMP.&MFC42.#800&
& &. 8B4C24 08& && &MOV ECX,DWORD PTR SS:[ESP+8]
& &. 5F& && && && & POP EDI
& &. 64:890D 000000&MOV DWORD PTR FS:[0],ECX
0040154D& &. 83C4 10& && &&&ADD ESP,10
& &. C3& && && && & RETN& && && && && && && && && && && && & ;&&看,在上面再处理一下后事,这个事件就退出了
& &&&90& && && && & NOP
& &&&90& && && && & NOP
& &&&90& && && && & NOP
每学一种新技术都有新的HELLO WORLD!
感谢发布原创作品,[吾爱破解论坛]因你更精.
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
带你阅读VC生成的经典反汇编代码,提高反汇编阅读能力没事在百度逛了下,看见有这样的方法提高反汇编能力!
刚写的关于如何提高反汇编代码阅读能力的帖子,顺便把一些call啊,堆栈平衡啊,局部变量访问啊这些东西结合实例说了一下
把自己写好的“hello world”程序源码加载到VC中,给main函数下个断点(F9下断点)
然后按F5运行至断点,VC把程序断下来的时候在断点代码处 右键菜单go to &&disassembly就可以看汇编代码了!
而且还是一行一行,源码对照反汇编解释给你看的。。
写一个小程序
#include &stdio.h&
void main(int argc[],char *argv[])
然后按照我刚才说的方法看汇编代码。。
用VC看汇编代码的好处就是能对照着看,坏处就是,如果你想看指定内存地址或者寄存器的数据的话,得自己在监视窗口中添加,很麻烦,调试程序时通常要眼观八方,注意数据寄存器,内存地址,和堆栈发生的变化,所以明显VC翻译汇编代码的功能着实有点好处,但比起OD来还是有点麻烦,那还是用回OD吧,程序载入时先执行的其实不是main函数,而是编译器生成的一些初始化代码,这些代码暂且不讨论吧,直接来到main函数吧,在OD中怎么到达main函数呢,在这里介绍一个技巧:
将程序改写成如下:
#include &stdio.h&
void main(int argc[],char *argv[])
char *a=&1234567&;
printf(&%s&,a);
然后将程序载入OD,右键-查看-所有参考文本串,在弹出的窗口中招字符串“12345”,然后双击这个字符串,OD就会把你带到main函数的附近了,到了main函数附近之后,就找push ebp吧(程序的经典开头代码)
下面把完整代码贴一遍(注意蓝色为main函数中代码 红色部分为一个校验堆栈平衡的一个函数。)
<font color="#401010 &&&55& && && && &&&push ebp& && && && && && && && && &; 保存原来的ebp
<font color="#401011& & 8BEC& && && && &mov ebp,esp& && && && && && && && &; 使得ebp=esp
<font color="#401013& & 83EC 44& && && &sub esp,44& && && && && && && && & ; 预留44h个字节的空间
上面一句的详细解释:上面预留的44h个字节空间即68个字节的空间,即预留17个变量的空间(每个变量4个字节),其中我们的程序定义了一个变量--即指向常量字符串的指针a
<font color="#401016& & 53& && && && &&&push ebx
<font color="#401017& & 56& && && && &&&push esi
<font color="#401018& & 57& && && && &&&push edi
;上面三句是因为后面要用到这三个寄存器 所以为了程序执行完后不改变寄存器值 而保存他们,程序执行完后恢复
<font color="#401019& & 8D7D BC& && && &lea edi,dword ptr ss:[ebp-44];将edi设置为栈中一块连续区域的首地址
<font color="#40101C& & B9 & &&&mov ecx,11& && && && && && && && & ; 11h=17,为什么要给ecx赋予17呢,我们往下看
<font color="#401021& & B8 CCCCCCCC& &&&mov eax,CCCCCCCC& && & ;为什么要给eax赋予8个c呢,我们往下看
<font color="#401026& & F3:AB& && && &&&rep stos dword ptr es:[edi]
现在开始解释上面三句,我先讲第三句吧,第三句的功能就是:将eax寄存器的值复制给由es:[edi]指向的内存区域,复制多少次呢?
ecx次!就是17次,就是将17个eax放到以es:[edi]为首地址的内存区域中,这样做没别的意思,就是初始化变量而已。
<font color="#401028& & C745 FC 1C00420&mov dword ptr ss:[ebp-4],CPPlearn.&; 把字符串常量的指针给ss:[ebp-4]也就是我们定义的指针变量a
<font color="#40102F& & 8B45 FC& && && &mov eax,dword ptr ss:[ebp-4]& && & ; 再将指a赋值给eax
<font color="#401032& & 50& && && && &&&push eax
<font color="#401033& & 68 B0074200& &&&push CPPlearn.& && && && & ; ASCII &%s&
<font color="#401038& & E8 & &&&call CPPlearn.printf
<font color="#40103D& & 83C4 08& && && &add esp,8& && && && && && && && &&&; 压栈调用函数,然后由主程序恢复堆栈平衡 压栈调用函数,你懂的!
<font color="#401040& & 5F& && && && &&&pop edi
<font color="#401041& & 5E& && && && &&&pop esi
<font color="#401042& & 5B& && && && &&&pop ebx& && && && && && && && && & ; 犯罪现场重现
<font color="#401043& & 83C4 44& && && &add esp,44& && && && && && && && & ; 释放掉占44h字节大小的在main中的所有变量
<font color="#401046& & 3BEC& && && && &cmp ebp,esp,在这里如果因为一些意外而使得恢复之后的esp不等于原来的esp(原来的esp保存在ebp)的话,将会出现一些问题,继续往下看
<font color="#ff48& & E8 C3000000& &&&call CPPlearn._chkesp
<font color="#ff10 & /75 01& && && &&&jnz short CPPlearn.& && &&&; 当ebp与esp相等时,属于正常情况,所以就不跳转了直接 返回主程序,其实我觉得这个判断应该由主程序来做,那就不用进call了,进call要浪费点时间。这里为了跟踪代码,我故意将Z标志位改成0(即比较结果不为0)
所以他的jnz就能实现跳转了。(跳到下面的401112去了)
<font color="#ff12& &|C3& && && && &&&retn
<font color="#ff13& &\55& && && && &&&push ebp& && && && && && && && && &; 又一个子程序,犯罪现场保存恢复这些垃圾话我就不说了
<font color="#ff14& & 8BEC& && && && &mov ebp,esp
<font color="#ff16& & 83EC 00& && && &sub esp,0
<font color="#ff19& & 50& && && && &&&push eax
<font color="#ff1A& & 52& && && && &&&push edx
<font color="#ff1B& & 53& && && && &&&push ebx
<font color="#ff1C& & 56& && && && &&&push esi
<font color="#ff1D& & 57& && && && &&&push edi
<font color="#ff1E& & 68 & &&&push CPPlearn.& && && && & ; ASCII &The value of ESP was not properly saved across a function call.&&This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. &
<font color="#ff23& & 68 & &&&push CPPlearn.
<font color="#ff28& & 6A 2A& && && &&&push 2A
<font color="#ff2A& & 68 & &&&push CPPlearn.& && && && & ; ASCII &i386\chkesp.c&
<font color="#ff2F& & 6A 01& && && &&&push 1
<font color="#ff31& & E8 CA140000& &&&call CPPlearn._CrtDbgReport//在这里会弹出一个警告的对话框,里面有调试按钮,忽略按钮 等等
<font color="#ff36& & 83C4 14& && && &add esp,14
<font color="#ff39& & 83F8 01& && && &cmp eax,1& && && && && && && && &&&; 在这里我点击了ignore按钮,所以跳过了下面的int 3指令
<font color="#ff3C& & 75 01& && && &&&jnz short CPPlearn.0040113F
<font color="#ff3E& & CC& && && && &&&int3
<font color="#ff3F& & 5F& && && && &&&pop edi& && && && && && && && && & ; 然后一直走着走着就回去了~~
<font color="#ff40& & 5E& && && && &&&pop esi
<font color="#ff41& & 5B& && && && &&&pop ebx
<font color="#ff42& & 5A& && && && &&&pop edx
<font color="#ff43& & 58& && && && &&&pop eax
<font color="#ff44& & 8BE5& && && && &mov esp,ebp
<font color="#ff46& & 5D& && && && &&&pop ebp
<font color="#ff47& & C3& && && && &&&retn
0040104D& & 8BE5& && && && &mov esp,ebp& && && && && && && && &; 程序执行完了,esp自然要恢复了
0040104F& & 5D& && && && &&&pop ebp& && && && && && && && && & ; 把原来的ebp要回来
& & C3& && && && &&&retn
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
头像被屏蔽
提示: 作者被禁止或删除 内容自动屏蔽
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
挺不错的。确实是一种学习的方法
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
分析一段C语言算法后,我懂得了汇编用于写程序的用途的抛弃的必然性
C语言一个简单算法的代码 没神马意义,就一个两层嵌套循环对一个二维数组的操作而已。
(本文中有QQ空间的图,如果图挂了 请到我qq空间看,不好意思 http://user.//blog/)
看汇编代码,几张图是连着的。
循环语句那一段经典代码我就不解释了。。参考&&天书夜读 从汇编语言到windows内核&&吧主要分析地址为411A6E到411AC1这里面的汇编语句吧(其实这里面就等于c[j]=&&a[0] * b[0][j] + a[1] * b[1][j] + a[2] * b[2][j];) 注意一下的话可以发现,mov 寄存器,dword ptr 这一句,经常出现,出现了四次,我以每次这条语句出现的地方作为一部分来讲解吧
看着这条表达式吧&&方便参考:c[j]=&&a[0] * b[0][j] + a[1] * b[1][j] + a[2] * b[2][j];
-------------------------------------第一部分-------------------------------------
eax=i*0Ch; 结构体元素偏移地址=第几个结构体*结构体元素大小ecx=a;
edx=j;eax=ecx+& & 结构元素地址=数组首址+结构体元素偏移地址
eax=eax*(esi+edx*4);
;esi是数组b的首址,edx是j,j=0 to 2,0=0*4(第0个下标元素)
& && && & 4=1*4(第1个下标元素)
& && && & 8=2*4(第2个下标元素)
& && && & 因为一维下标总是0所以才可以用这种方式寻址数组
-------------------------------------第一部分--------------------------------------------------------------------------第二部分-------------------------------------
ecx=i*0Ch;& &结构体元素偏移地址=第几个结构体*结构体元素大小edx=a;
esi=j;ecx=edx+ecx+4;& && &结构元素地址=数组首址+结构体元素偏移地址+4个字节(不加4字节就是第0个下标元素,加了自然就是第一个了)
ecx=ecx*(edi+esi*4+0ch); ecx求出来了,现在要累乘,结果还是放在ecx。edi为b首址,esi为j j*4字节就是:第j个元素所在字节位置,
& && && &&&然后再加了0ch是因为一维坐标始终为1,即一维坐标为0时造成的3个int元素
& && && &&&我们还得加上去,3*4字节=12字节=0ch字节,所以要加0ch
add eax,& &已经有两个表达式计算出来了,所以先将它们加起来吧
-------------------------------------第二部分--------------------------------------------------------------------------第三部分-------------------------------------
edx=i*0Ch;& &结构体元素偏移地址=第几个结构体*结构体元素大小ecx=a;
esi=j;edx=edi+edx+8;& &b的首址+结构体元素偏移地址+第2个下标元素(即第3个数组元素,所以+8字节)
edx=edx*(edi+(esi*4)+18h) edx照乘,被乘数为b的首址+一维下标为2造成的18h个字节的占用+j*4字节。add eax,edx& &最后结果在eax中了-------------------------------------第三部分--------------------------------------------------------------------------第四部分-------------------------------------
ecx=i*0Ch;& &结构体元素偏移地址=第几个结构体*结构体元素大小ecx=ecx+cedx=j
ecx+edx*4=eax;& &这句当然是把结果给c[j]了
-------------------------------------第四部分-------------------------------------
图片可以重新补一下吗?麻烦您了
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限25
哇咔咔&&看看
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
在百度搜了个C语言常用算法.docx。便拿起最简单的一个小算法来练习下反汇编了
程序源代码:#include&stdio.h&#include&stdlib.h& int sushu(int m); void main(){ & &&&int m,k; & &&&printf(&please input a number:\n&);& &&&scanf(&%d&,&m); & &&&k=sushu(m); & &&&if(k==m)& &&&printf(&该数是素数\n&);& &&&else& &&&printf(&该数不是素数\n&);& &&&system(&pause&);} int sushu(int m){&&&&for(i=2;i*i&=m;i++)& &&&if(m%i==0)& && &&&return 0;&&} 逆向思路:用OD打开程序 F8单步走,走到一个Call 卡主,因为程序在正式运行了,要求输入了在那个call下断点重新加载程序 F9运行到断点,然后F7跟进CALL。Call里面是主程序内容,这里主要分析sushu函数,再走几步找到sushu函数进去,汇编代码:& & 56& && && && &&&push esi
& & 8B7424 08& && & mov esi,dword ptr ss:[esp+8]& && && && & ; esi作传进来的参数
& & 83FE 04& && && &cmp esi,4& && && && && && && && && && &&&; m&=i*i
& & B9 & &&&mov ecx,2& && && && && && && && && && &&&; i=2
0040100D& & 7C 14& && && &&&jl short asm.& && && && && && &&&; 小于4的话直接跳过 返回素数本身
0040100F& & 90& && && && &&&nop
& & 8BC6& && && && &mov eax,esi& && && && && && && && && && &; 参数暂时给eax
& & 99& && && && &&&cdq& && && && && && && && && && && && &&&; 将eax的符号位扩展到edx
& & F7F9& && && && &idiv ecx& && && && && && && && && && && &; 合并后除以ecx 商放在eax 余数放在edx
& & 85D2& && && && &test edx,edx
& & 74 0E& && && &&&je short asm.& && && && && && &&&; 如果等于0,即没有余数 就判断它不是素数
& & 41& && && && &&&inc ecx& && && && && && && && && && && & ; i++;
0040101A& & 8BC1& && && && &mov eax,ecx
0040101C& & 0FAFC1& && && & imul eax,ecx& && && && && && && && && &&&; 综合两句得 i*i
0040101F& & 3BC6& && && && &cmp eax,esi
&&^ 7E ED& && && &&&jle short asm.& && && && && && & ; i*i小于等于4则循环继续
& & 8BC6& && && && &mov eax,esi
& & 5E& && && && &&&pop esi
& & C3& && && && &&&retn
& & 33C0& && && && &xor eax,eax
& & 5E& && && && &&&pop esi
0040102A& & C3& && && && &&&retn ---------------------------------------多多练习!
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
随机生成一百个数 个位为x的数有y个 求x和y这次笔记难度加大一点了!有比较多的跳转和循环,还包含数组寻址~~~
笔记还是整理漂亮一点吧,以后可能要拿来做教程。
C源代码,,VC编译无压力过:
#include &stdio.h&
#include &stdlib.h&
void main()
&&int a[101],x[11],i,p;
&&for(i=0;i&=10;i++)
&&for(i=1;i&=100;i++)
& &a=rand() % 100;
& &printf(&%4d&,a);
& &if(i%10==0)
& &printf(&\n&);
&&for(i=1;i&=100;i++)
&&{& && && && && &p=a%10;
& &&&if(p==0) p=10;
& &&&x[p]=x[p]+1;
&&for(i=1;i&=10;i++)
&&{& && & p=i;
& & if(i==10) p=0;
& & printf(&%d,%d\n&,p,x);
&&printf(&\n&);
&&system(&pause&);
(之前从VS2008复制过来的时候代码有高亮的,现在换了VC6就木有了。。)
进入正题!
照样F8到程序跑飞,断下Call F7跟进代码如下
& && & 81EC C0010000& && &sub esp,1C0& && && && && && && && && && &; 1c0=448,448=101*4+11*4
& && & B9 0B000000& && &&&mov ecx,0B& && && && && && && && && && & ; ecx=11
0040100B& && & 33C0& && && && && &xor eax,eax& && && && && && && && && && &; eax=0
0040100D& && & 56& && && && && &&&push esi
0040100E& && & 57& && && && && &&&push edi
0040100F& && & 8D7C24 08& && && & lea edi,dword ptr ss:[esp+8]& && && && & ; 访问缓冲区的地址
& && & BE & && &&&mov esi,1& && && && && && && && && && &&&; esi=1
& && & F3:AB& && && && &&&rep stos dword ptr es:[edi]& && && && &&&; 将eax往es:[edi]放11次
0040101A& && & 8D7C24 38& && && & lea edi,dword ptr ss:[esp+38]& && && && &; 访问数组x的末尾+1也就是数组a的起始
0040101E& && & E8 & && &&&call asm.& && && && && && && && &; rand
& && & 99& && && && && &&&cdq& && && && && && && && && && && && &&&; edx变成eax的符号位
& && & B9 & && &&&mov ecx,64& && && && && && && && && && & ; ecx=100
& && & F7F9& && && && && &idiv ecx& && && && && && && && && && && &; eax除以ecx,商在eax 余数在edx
0040102B& && & 52& && && && && &&&push edx
0040102C& && & 68 & && &&&push asm.& && && && && && && && &; ASCII &%4d&
& && & 8917& && && && && &mov dword ptr ds:[edi],edx& && && && && &; 把余数转存到ds:[edi]??噢噢.. ds:[edi]就是相当于a了
& && & E8 2E010000& && &&&call asm.
& && & 8BC6& && && && && &mov eax,esi
0040103A& && & B9 0A000000& && &&&mov ecx,0A
0040103F& && & 99& && && && && &&&cdq
& && & F7F9& && && && && &idiv ecx& && && && && && && && && && && &; eax除以10
& && & 83C4 08& && && && &add esp,8& && && && && && && && && && &&&; 我靠,401033call的堆栈平衡的语句还跑那么远来执行
& && & 85D2& && && && && &test edx,edx
& && & 75 0D& && && && &&&jnz short asm.
& && & 68 & && &&&push asm.
0040104E& && & E8 & && &&&call asm.
& && & 83C4 04& && && && &add esp,4& && && && && && && && && && &&&; 还是堆栈平衡,这次像样点。
& && & 46& && && && && &&&inc esi
& && & 83C7 04& && && && &add edi,4
0040105A& && & 83FE 64& && && && &cmp esi,64
0040105D& &&&^ 7E BF& && && && &&&jle short asm.0040101E
0040105F& && & 8D4C24 38& && && & lea ecx,dword ptr ss:[esp+38]& && && && &; 数组a的地址放到ecx
& && & BE & && &&&mov esi,64& && && && && && && && && && & ; esi=100
& && & 8B01& && && && && &mov eax,dword ptr ds:[ecx]& && && && && &; 循环起始
0040106A& && & BF 0A000000& && &&&mov edi,0A& && && && && && && && && && & ; edi=10
0040106F& && & 99& && && && && &&&cdq
& && & F7FF& && && && && &idiv edi
& && & 85D2& && && && && &test edx,edx
& && & 75 02& && && && &&&jnz short asm.& && && && && && & ; if eax/10没有余数则跳转
& && & 8BD7& && && && && &mov edx,edi
& && & 8B7C94 08& && && & mov edi,dword ptr ss:[esp+edx*4+8]& && & ; 这两条啊 +了8,是因为之前还push了两个寄存器 还记得吗?就是最前面的那两个push
0040107C& && & 8D4494 08& && && & lea eax,dword ptr ss:[esp+edx*4+8]& && & ; 从上面三句看出 edx是作为变量p了
& && & 47& && && && && &&&inc edi
& && & 83C1 04& && && && &add ecx,4& && && && && && && && && && &&&; 把a数组的下标往后挪
& && & 4E& && && && && &&&dec esi
& && & 8938& && && && && &mov dword ptr ds:[eax],edi
& &&&^ 75 DF& && && && &&&jnz short asm.& && && && && && & ; 循环结束
& && & BE & && &&&mov esi,1& && && && && && && && && && &&&; esi是循环变量咯
0040108E& && & 83FE 0A& && && && &cmp esi,0A
& && & 8BC6& && && && && &mov eax,esi
& && & 75 02& && && && &&&jnz short asm.
& && & 33C0& && && && && &xor eax,eax
& && & 8B54B4 08& && && & mov edx,dword ptr ss:[esp+esi*4+8]
0040109B& && & 52& && && && && &&&push edx
0040109C& && & 50& && && && && &&&push eax
0040109D& && & 68 & && &&&push asm.& && && && && && && && &; ASCII &%d,%d
& && & E8 BF000000& && &&&call asm.
& && & 83C4 0C& && && && &add esp,0C
004010AA& && & 46& && && && && &&&inc esi
004010AB& && & 83FE 0A& && && && &cmp esi,0A
004010AE& &&&^ 7E DE& && && && &&&jle short asm.0040108E
& && & 68 & && &&&push asm.
& && & E8 AC000000& && &&&call asm.
004010BA& && & 68 & && &&&push asm.& && && && && && && && &; ASCII &pause&
004010BF& && & E8 0C000000& && &&&call asm.
& && & 83C4 08& && && && &add esp,8
& && & 5F& && && && && &&&pop edi
& && & 5E& && && && && &&&pop esi
& && & 81C4 C0010000& && &add esp,1C0
004010CF& && & C3& && && && && &&&retn
这次逆向的这个算法总结了一些经验 分享一下
1&&遇到跳转跨度较大的,例如跨了20条语句左右的,那大概就是一个C语言里的for while do这些循环了。
2&&认清循环之后要找准循环变量再进行后续分析
3 很多时候程序会以ecx作为循环变量,如果ecx用作其他用途的话 也会选择其他寄存器做循环变量
4 在程序里面有些局部变量编译器会直接用寄存器把他替换掉,所以要认清哪个寄存器把这个变量替换掉了
& && & 81EC C0010000& && &sub esp,1C0& && && && && && && && && && &; 1c0=448,448=101*4+11*4
& && & B9 0B000000& && &&&mov ecx,0B& && && && && && && && && && & ; ecx=11
0040100B& && & 33C0& && && && && &xor eax,eax& && && && && && && && && && &; eax=0
0040100D& && & 56& && && && && &&&push esi
0040100E& && & 57& && && && && &&&push edi
0040100F& && & 8D7C24 08& && && & lea edi,dword ptr ss:[esp+8]& && && && & ; 访问缓冲区的地址
这里的最后一条语句的意思我开始以为是访问CALL语句的下一条指令的地址呢,原来是因为在程序开头用sub esp,1c0开辟了一段缓冲区,
然后push了两个寄存器,所以访问这段缓冲区自然就是esp+8了
程序开始时分配的这一段缓冲区是一下子分配给了一个或者一个以上的数组和变量了,这里的缓冲区包含数组a和数组x
原来后声明的变量还排在缓冲区的前面。。也就是,这里的缓冲区数组x的11个元素排前面 接着才是数组a
从这里可以看出:0040101A& && & 8D7C24 38& && && & lea edi,dword ptr ss:[esp+38]& && && && &; 访问数组x的末尾+1也就是数组a的起始
esp+38,38h也就是56D,就是56了,56减去之前的两个寄存器占的8个字节,也就是48了,每个int变量占4个字节,那么这里就是有12个变量了,什么?12???,x不是11个元素吗?怎么成12了,呵呵因为第12已经是接下来的数组的第一个元素了!!
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
冒泡算法的分析
冒泡算法,以前学C的时候看到这名字就觉得深奥不敢看。。。。
& &int i,j,
& &int a[5];
& &for(i=0;i&5;i++)
& &scanf (&%d,&,&a); //输入5个数
& &for(i=0;i&=4;i++)
& & for (j=0;j&5-i;j++)
& &&&if (a[j]&a[j+1])
& && &temp=a[j];
& && &a[j]=a[j+1];
& && &a[j+1]=
& &for(i=0;i&5;i++)
& &printf(&%5d,&,a );
& &printf(&\n&);
老做法!F8单步到跑飞CALL断下重新加载进Call分析!(好一个从句!)
& && & 83EC 14& && && && && &sub esp,14& && && && && && && && && && & ; 14h=20,20=4*5
& && & 56& && && && && && &&&push esi
& && & 57& && && && && && &&&push edi& && && && && && && && && && && &; 保存现场
& && & 8D7424 08& && && && & lea esi,dword ptr ss:[esp+8]& && && && & ; 访问sub esp,14空出的缓冲区的首址
& && & BF & && && &&&mov edi,5& && && && && && && && && && &&&; edi=5
0040100E& && & 56& && && && && && &&&push esi& && && && && && && && && && && &; 把缓冲区用来接收数字(输入循环的开始)
0040100F& && & 68 3C804000& && && &&&push asm.0040803C& && && && && && && && &; ASCII &%d,&
& && & E8 & && && &&&call asm.& && && && && && && && &; scanf
& && & 83C4 08& && && && && &add esp,8& && && && && && && && && && &&&; 恢复两个单位的堆栈(以后我们就称4个字节为一个单位吧)
0040101C& && & 83C6 04& && && && && &add esi,4& && && && && && && && && && &&&; 指向缓冲区的指针加一个单位,即指向下一个元素
0040101F& && & 4F& && && && && && &&&dec edi& && && && && && && && && && && & ; edi--;
& &&&^ 75 EC& && && && && &&&jnz short asm.0040100E& && && && && && & ; edi为0就退出循环(即初始化5个元素)(输入循环的结束)
& && & BF & && && &&&mov edi,5& && && && && && && && && && &&&; edi=5
& && & 85FF& && && && && && &test edi,edi& && && && && && && && && &&&; 大循环的开始(嵌套) 两个正整数相与,结果不为0所以Z为0&&直到edi减小为0时或者本来就为0时这个操作才会导致Z=1 由于大循环结束处有cmp edi,1和jge跳转所以这里的jle循环算是废的了
& && & 7E 1A& && && && && &&&jle short asm.& && && && && && & ; 把它nop掉试试 ……结果运行也没错呵呵
0040102B& && & 8D4424 0C& && && && & lea eax,dword ptr ss:[esp+C]& && && && & ; 缓冲区的第二个变量放在eax,也就是冒泡中所谓的a[j+1]了
0040102F& && & 8BF7& && && && && && &mov esi,edi& && && && && && && && && && &; 第一次循环的时候i和j相同都是5 只是在小循环里面j就是(esi)才递减了
& && & 8B48 FC& && && && && &mov ecx,dword ptr ds:[eax-4]& && && && & ; 前一个变量(循环开始)
& && & 8B10& && && && && && &mov edx,dword ptr ds:[eax]& && && && && &; 后一个变量
& && & 3BCA& && && && && && &cmp ecx,edx& && && && && && && && && && &; 比较一下
& && & 7E 05& && && && && &&&jle short asm.0040103F& && && && && && & ; 如果大于则调位(小于则不调位)
0040103A& && & 8950 FC& && && && && &mov dword ptr ds:[eax-4],edx
0040103D& && & 8908& && && && && && &mov dword ptr ds:[eax],ecx& && && && && &; 上面两句是调位代码
0040103F& && & 83C0 04& && && && && &add eax,4& && && && && && && && && && &&&; j++;
& && & 4E& && && && && && &&&dec esi& && && && && && && && && && && & ; 这里跟j++其实也差不多,只不过esi是用于计数,而没有用来寻址而已
& &&&^ 75 EC& && && && && &&&jnz short asm.& && && && && && & ; 循环结束
& && & 4F& && && && && && &&&dec edi
& && & 83FF 01& && && && && &cmp edi,1
& &&&^ 7D DC& && && && && &&&jge short asm.& && && && && && & ; 大循环的结束(嵌套)
0040104B& && & 8D7424 08& && && && & lea esi,dword ptr ss:[esp+8]& && && && & ; 拿第一个数组元素
0040104F& && & BF & && && &&&mov edi,5& && && && && && && && && && &&&; 输出5次吧
& && & 8B06& && && && && && &mov eax,dword ptr ds:[esi]& && && && && &; 输出循环的开始
& && & 50& && && && && && &&&push eax
& && & 68 & && && &&&push asm.& && && && && && && && &; ASCII &%5d,&
0040105C& && & E8 1F000000& && && &&&call asm.
& && & 83C4 08& && && && && &add esp,8
& && & 83C6 04& && && && && &add esi,4
& && & 4F& && && && && && &&&dec edi
& &&&^ 75 EA& && && && && &&&jnz short asm.& && && && && && & ; 输出循环的结束
0040106A& && & 68 & && && &&&push asm.
0040106F& && & E8 0C000000& && && &&&call asm.& && && && && && && && &; printf
& && & 83C4 04& && && && && &add esp,4& && && && && && && && && && &&&; 最后输出换行符
& && & 5F& && && && && && &&&pop edi& && && && && && && && && && && & ; 上面这些跟开头差不多了,只不过一个输入 一个输出罢了
& && & 5E& && && && && && &&&pop esi
& && & 83C4 14& && && && && &add esp,14
0040107C& && & C3& && && && && && &&&retn
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
阅读权限10
逆向一些在百度找到的简单的C语言算法
今天好不容易在网管中心的一台垃圾机子上装好VC和OD。。
在百度找到一些简单,适合用来反汇编的算法: http://blog.csdn.net/yanfan0916/article/details/6450472
程序源码:
#include &stdio.h&
#include &stdlib.h&
void main()
int i,j,k;
printf(&\n&);
for(i=1;i&5;i++)
&&for(j=1;j&5;j++)
& &for(k=1;k&5;k++)
& & if(i!=k&&i!=j&&j!=k)
& & printf(&%d,%d,%d/n&,i,j,k);
OD载入,一直F8走,发现竟然没有停住直接结束了程序,原来因为本C程序中未有要求用户输入的函数,所以
我们要自己注意OD中代码调用了哪个call之后屏幕开始输出数据了。
&&|.&&E8 BBFEFFFF& &call& &
走到这里的时候发现已经有东西输出了,于是断下 重新加载程序 运行到此处再F7单步!
OD反汇编代码:
&&/$&&53& && && && &push& & ebx
&&|.&&56& && && && &push& & esi
&&|.&&57& && && && &push& & edi& && && && && && && && && && &;&&看来就是把这三个寄存器当做i j k了
&&|.&&68 3C704000& &push& & 0040703C
&&|.&&E8 & &call& & & && && && && && && && & ;&&输出空行
0040100D&&|.&&83C4 04& && & add& &&&esp, 4& && && && && && && && && &;&&恢复堆栈(C函数)
&&|.&&BB & &mov& &&&ebx, 1& && && && && && && && && &;&&i
&&|&&&BF & &/mov& &&&edi, 1& && && && && && && && &&&;&&j
0040101A&&|&&&BE & &|/mov& &&&esi, 1& && && && && && && && & ;&&k
0040101F&&|&&&3BDE& && && & ||/cmp& &&&ebx, esi& && && && && && && & ;&&cmp i,k
&&|.&&74 18& && && &|||je& && &short 0040103B& && && && && & ;&&不符合条件i!=k则跳转,进入本层循环的下一次循环或因循环变量不小于5而退出本层
&&|.&&3BDF& && && & |||cmp& &&&ebx, edi
&&|.&&74 14& && && &|||je& && &short 0040103B& && && && && & ;&&不符合条件i!=j则跳转,进入本层循环的下一次循环或因循环变量不小于5而退出本层
&&|.&&3BFE& && && & |||cmp& &&&edi, esi
&&|.&&74 10& && && &|||je& && &short 0040103B& && && && && & ;&&不符合条件j!=k则跳转,进入本层循环的下一次循环或因循环变量不小于5而退出本层
0040102B&&|.&&56& && && && &|||push& & esi
0040102C&&|.&&57& && && && &|||push& & edi
0040102D&&|.&&53& && && && &|||push& & ebx
0040102E&&|.&&68 & &|||push& & & && && && && && && & ;&&ASCII &%d,%d,%d/n&
&&|.&&E8 & &|||call& & & && && && && && && & ;&&如果都符合就输出吧
&&|.&&83C4 10& && & |||add& &&&esp, 10& && && && && && && &&&;&&恢复堆栈
0040103B&&|&&&46& && && && &|||inc& &&&esi& && && && && && && && && &;&&k++
0040103C&&|.&&83FE 05& && & |||cmp& &&&esi, 5
0040103F&&|.^ 7C DE& && && &||\jl& && &short 0040101F& && && && && & ;&&k&5则跳转
&&|.&&47& && && && &||inc& &&&edi& && && && && && && && && & ;&&j++
&&|.&&83FF 05& && & ||cmp& &&&edi, 5
&&|.^ 7C D3& && && &|\jl& && &short 0040101A& && && && && &&&;&&j&5则跳转
&&|.&&43& && && && &|inc& &&&ebx
&&|.&&83FB 05& && & |cmp& &&&ebx, 5
0040104B&&|.^ 7C C8& && && &\jl& && &short & && && && && && &;&&i&5则跳转
0040104D&&|.&&5F& && && && &pop& &&&edi& && && && && && && && && && &;&&恢复现场
0040104E&&|.&&5E& && && && &pop& &&&esi
0040104F&&|.&&5B& && && && &pop& &&&ebx
&&\.&&C3& && && && &retn
OD的那些跳转的连线还真给我们省事,一眼就能看出是三层循环。
发帖求助前要善用【】功能,那里可能会有你要找的答案;如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】和【CB】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
免责声明:吾爱破解所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
( 京ICP备号 | 京公网安备 87号 )
Powered by Discuz!
Comsenz Inc.

我要回帖

更多关于 错误代码y2001 的文章

 

随机推荐