本人是单片机初学求C语言红外遥控解码程序并用数码管显示带注悉

本人是单片机初学求C语言红外遥控解码程序并用数码管显示带注悉,第1张

#include <reg51h>

#include <intrinsh>

#define uchar unsigned char

#define uint unsigned int

sbit IRIN = P3^2; //遥控输入脚

sbit BEEP = P3^7; //蜂鸣器

sbit RELAY= P3^6; //继电器

uchar IR_buf[4]={0x00,0x00,0x00,0x00};//IR_buf[0]、IR_buf[1]为用户码低位、用户码高位接收缓冲区

// IR_buf[2]、IR_buf[3]为键数据码和键数据码反码接收缓冲区

uchar disp_buf[2]={0x10,0x10}; //显示缓冲单元,初值为0x10(即16),指向显示码的第16个"-"

uchar code seg_data[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf};

//0~F和"-"符的显示码(字形码)

/以下是014ms的x倍延时函数/

void delay(uchar x) //延时x014ms

{

uchar i;

while(x--)

for (i = 0; i<13; i++);

}

/以下是延时函数/

void Delay_ms(uint xms)

{

uint i,j;

for(i=xms;i>0;i--) //i=xms即延时约xms毫秒

for(j=110;j>0;j--);

}

/以下是蜂鸣器响一声函数/

void beep()

{

BEEP=0; //蜂鸣器响

Delay_ms(100);

BEEP=1; //关闭蜂鸣器

Delay_ms(100);

}

/以下是显示函数/

void Display()

{

P0=(seg_data[disp_buf[0]]);

P2=0x7f;

Delay_ms(1);

P0=(seg_data[disp_buf[1]]);

P2=0xbf;

Delay_ms(1);

}

/以下是主函数/

main()

{

EA=1;EX0=1; //允许总中断中断,使能 INT0 外部中断

IT0 = 1; //触发方式为脉冲负边沿触发

IRIN=1; //遥控输入脚置1

BEEP=1; RELAY=1; //关闭蜂鸣器和继电器

P0=0xff; P2=0xff; //P0和P2口置1

Display(); //调显示函数

while(1)

{

if(IR_buf[2]==0x02) //02H键(键值码为02H)

RELAY=0; //继电器吸合

if(IR_buf[2]==0x01) // 01H键(键值码为01H)

RELAY=1; //继电器关闭

Display();

}

}

/以下是外中断0函数/

void IR_decode() interrupt 0

{

uchar j,k,count=0;

EX0 = 0; //暂时关闭外中断0中断请求

delay(20); //延时20014=28ms

if (IRIN==1) //等待 IRIN低电平出现

{

EX0 =1; //开外中断0

return; //中断返回

}

while (!IRIN) delay(1); //等待IRIN变为高电平,跳过9ms的低电平引导码

for (j=0;j<4;j++) //收集四组数据,即用户码低位、用户码高位、键值数据码和键值数码反码

{

for (k=0;k<8;k++) //每组数据有8位

{

while (IRIN) //等待IRIN变为低电平,跳过45ms的高电平引导码信号。

delay(1);

while (!IRIN) //等待IRIN变为高电平

delay(1);

while (IRIN) //对IRIN高电平时间进行计数

{

delay(1); //延时014ms

count++; //对014ms延时时间进行计数

if (count>=30)

{

EX0=1; //开外中断0

return; //014ms计数过长则返回

}

}

IR_buf[j]=IR_buf[j] >> 1; //若计数小于6,数据最高位补"0",说明收到的是"0"

if (count>=6) {IR_buf[j] = IR_buf[j] | 0x80;} //若计数大于等于6,数据最高位补"1",说明收到的是"1"

count=0; //计数器清0

}

}

if (IR_buf[2]!=~IR_buf[3]) //将键数据反码取反后与键数据码码比较,若不等,表示接收数据错误,放弃

{

EX0=1;

return;

}

disp_buf[0]=IR_buf[2] & 0x0f; //取键码的低四位送显示缓冲

disp_buf[1]=IR_buf[2] >> 4; //右移4次,高四位变为低四位送显示缓冲

Display(); //调显示函数

beep(); //蜂鸣器响一声

EX0 = 1; //开外中断0

}

gh0st远控软件采用驱动级RESSDT过主动,svchost参数启动,替换系统服务的方式工作的,工作方式较为先进,美中不足的部分是没有进行驱动级或用户级隐藏,当然这部分可以添加进去。编码利用了VC的编程环境。

一、环境配置

编译环境一定要配置好:DDK+SDK+VC6,DDK用来编译sys文件的,SDK+VC6是用来编译工程的,配置部分比较简单,网上有很多资料,这里不再详述,有兴趣的朋友也可以查看DDK和SDK的相关帮助。

二、特征码定位简述

杀毒软件查杀木马的原理基本是根据特征查杀的,被查杀的部分我们称之为特征码,所以我们可以利用特征码定位工具MyCLL定位出病毒的特征码位置,定位工具原理是将被扫描木马分块,利用分段填充的方式,匹配杀软的特征值,找到杀软查杀病毒的位置。

定位出特征码,如何反向找到源码中的对应位置呢?请看下面分析,

三、二进制文件与源码定位之map文件利用

map文件是二进制和源码之间对应的一个映射文件。

我们假设根据第三步我们定位出了病毒的特征码:

病毒名称 特征码位置 内存地址

svchostdll 000038AA_00000002 100044AA

svchostdll 00005F98_00000002

第一步设置VC编译环境生成Map文件。

在 VC 中,点击菜单“Project -> Settings”选项页(或按下 Alt+F7),选择 C/C++ 选项卡,并在最下面的 Project Options 里面输入:/Zd ,然后要点击 Link 选项卡,选中“Generate mapfile”复选框,并在最下面的 Project Options 里面输入:/mapinfo:lines,表示生成 MAP 文件时,加入行信息。设置完成。

第二步编译VC工程,设置活动工程编译即可,这个不用说明。这个步骤完成后,在release(或debug)目录,多了一个map文件(比如svchostmap)。

第三步打开map文件(用UE或文本编辑器打开都行),形式如下:

(begin)

Timestamp is 488fcef2 (Wed Jul 30 10:16:18 2008)

Preferred load address is 10000000

---------------------------------------------------------------------------1----(为方便说明,wrw添加)

Start Length Name Class

0001:00000000 00010a50H text CODE

0001:00010a50 00000485H text$x CODE

0002:00000000 000004c8H idata$5 DATA

0003:00000010 00000004H CRT$XIZ DATA

0003:00000020 00001a50H data DATA

0003:00001a70 00000688H bss DATA

0004:00000000 000000a8H rsrc$01 DATA

0004:000000b0 00000cf0H rsrc$02 DATA

----------------------------------------------------------------------------2---(为方便说明,wrw添加)

Address Publics by Value Rva+Base Lib:Object

0001:00000000 0CAudio@@QAE@XZ 10001000 f Audioobj

0001:000000d0 _GCAudio@@UAEPAXI@Z 100010d0 f i Audioobj

0001:000000d0 _ECAudio@@UAEPAXI@Z 100010d0 f i Audioobj

0001:000000f0 1CAudio@@UAE@XZ 100010f0 f Audioobj

0001:000001e0 getRecordBuffer@CAudio@@QAEPAEPAK@Z 100011e0 f Audioobj

0001:00000240 playBuffer@CAudio@@QAE_NPAEK@Z 10001240 f Audioobj

0001:000002c0 InitializeWaveIn@CAudio@@AAE_NXZ 100012c0 f Audioobj

0001:00003310 SendToken@CFileManager@@AAEHE@Z 10004310 f FileManagerobj

0001:00003320 UploadToRemote@CFileManager@@AAE_NPAE@Z 10004320 f FileManagerobj

0001:00003440 FixedUploadList@CFileManager@@AAE_NPBD@Z 10004440 f FileManagerobj

0001:00003670 StopTransfer@CFileManager@@AAEXXZ 10004670 f FileManagerobj

0001:00003730 CreateLocalRecvFile@CFileManager@@AAEXPAE@Z 10004730 f FileManagerobj

----------------------------------------------------------------------------3---(为方便说明,wrw添加)

Line numbers for \Release\FileManagerobj(E:\vtmp\gh0st3src\Server\svchost\common\FileManagercpp) segment text

17 0001:00002630 20 0001:0000267f 21 0001:00002698 24 0001:000026d0

25 0001:000026f8 26 0001:0000273c 29 0001:000027d0 33 0001:000027ee

77 0001:000027f8 36 0001:000027fb 37 0001:00002803 77 0001:0000280d

532 0001:0000340f 534 0001:00003414 537 0001:00003428 540 0001:00003440

546 0001:0000345d 547 0001:00003487 548 0001:00003490 549 0001:00003492

551 0001:0000349e 552 0001:000034b8 553 0001:000034cb 554 0001:000034d4

558 0001:000034de 560 0001:000034e9 563 0001:000034ee 564 0001:00003506

(end)

我们看下,定位svchostdll 的第一个特征码内存地址为:100044AA,在第2块中,我们可以找到RVA+BASE与之很接近的是

0001:00003440 FixedUploadList@CFileManager@@AAE_NPBD@Z 10004440 f FileManagerobj

这样我们可以定位到FileManagercpp中的FixedUploadList函数,是不是范围缩小了?

下面我们再缩小代码行

利用这个公式:特征码行偏移 = 特征码地址(Crash Address)- 基地址(ImageBase Address)- 0x1000

看起来好像很难,其实很简单,我们将100044AA去掉内存基址10000000,再减1000,因为PE很多从1000开始,可以得到代码偏移地址为34AA。到第3块中找对应的代码行。

偏移地址34AA在(551 0001:0000349e 552 0001:000034b8 )中间,也就是551行和552行中间,我们到源程序中查找第551行:

wsprintf(lpszFilter, "%s%s", lpPathName, lpszSlash);

这样就定位出源代码了,要怎么修改就怎么修改它就可以了。

四、实战免杀

A、卡巴免杀

首次编译后,先做卡巴的免杀。卡巴杀sys文件和dll,当然也就杀包装它们的installexe,最后卡巴还杀生成的sever,我这里说杀生成好的server不是和前面的特征码重叠的地方,而是杀配置信息。

第一步、sys免杀

sys重新编译后,增加了输入表的函数,同时系统不同,造成很多地方不同于原特征,顺利通过卡巴、金山、小红伞等杀软。

第二步、svchostdll免杀

特征码定位MultiByteToWideChar和"gh0st update"两个位置。这里是通过第3步map文件得出的。

卡巴怕加花指令, 这个函数MultiByteToWideChar的调用上,可以在这个函数前面随便加几句无效语句就可以通过卡巴杀软。

字符串调用"gh0st update" ,这个是用于更新用的 ,如果不要在线更新,直接把这个语句所在代码块删除;嘿嘿,其实搜索工程替换这个字符串为其他的字符串就可以了^_^,这个方法同时可以过金山杀软。

第三步、server免杀

卡巴定位在最后的配置信息,采取跳转显然是不行的,采用加花的办法,在写入AAAAAA配置信息之前,随便写些东西,就可以做server免杀。

卡巴免杀完成!

B、Avast免杀

最新的avast杀软再查杀1下,杀installexe和svchostdll(也就是杀生成的文件和其中的资源文件),接着做它的源码免杀。

定位在特征字符串%02d/%02d/%02d和“SYSTEM\CurrentControlSet\Services\%s”两个地方。

解决方案:

1、svchostdll的特征码定位在键盘记录KeyboardManagercpp文件中的SaveInfo(char lpBuffer)函数。特征字符串%02d/%02d/%02d,也就是我们看到键盘记录的日期,修改之,修改的方法很多,将其改为[%d/%d/%d %d:%d:%d] ,编译即可通过avast杀软。

2、install的特征码定位在“SYSTEM\CurrentControlSet\Services\%s”,对应文件是installcpp里的InstallService函数,修改大小写,编译即可通过免杀。

五、添加垃圾代码的小方法

垃圾代码要移动特征码所在的位置,不要跑到堆栈中了,这样的代码没有用。可以采取添加for循环,做计数,简单统计,采用局部变量,不改变后面的逻辑为宜。

添加输出表的方法:

有杀输出表的,可以在生成的svchostdll上添加空函数 ,但是每次编译都要修改1次资源 ,其实我们在源码上添加如下语句:

extern "C" __declspec(dllexport) bool JustTempFun();//声明

……

extern "C" __declspec(dllexport) bool JustTempFun() //实现

{

return false;

}

编译后,输出表就被改变了,有的杀软就可做到代码免杀。

六、gh0st自动生成6to4exdll的修改

看到好多站友提问自动生成6to4exdll的问题,有热心站友也提出了自己的见解 ,我感觉有些人提出的解决方案不完全正确,有可能造成刚入手人误解,我根据自己的理解说明1下。

gh0st服务端是通svchost -netsvcs启动的,所以程序要利用netsvcs 服务,服务端也就是根据netsvcs生成的,故不能说服务端生成是随机的,相对于大多数系统来讲,基本是固定的,下面看分析。

查看installcpp里面的InstallService()方法,首先遍历HKEY_LOCAL_MACHINE\SOFTWARE\ Microsoft\Windows NT\CurrentVersion\Svchost中的服务项,查找到一个服务后,程序采取替换服务的方法,将原服务删除,然后生成对应服务项+ exdll的文件替换原服务,6to4服务一般排在第一位,6to4服务是一种自动构造隧道的方式,作用在于只需要一个全球惟一的IPv4地址便可使得整个站点获得IPv6 的连接,这个服务对一般人来讲,基本闲置,所以我们的程序就把6to4服务给替换掉,同时在windows\system32\目录下生成 6to4exdll,以后启动就是6to4ex了,如果把这个服务跳过去,就依次向下生成Ias、Iprip等服务啦,如果netsvcs项没有可以替换的服务,则程序将自己添加1个服务,名称就是由 AddsvchostService()方法产生的netsvcs_0x%d。

这样说不知道关心服务名称的明白了不?

这个不能说是技术问题,但是小技巧问题可以从这里产生,我不知道其他人的360是怎么过的,但是我觉得可以提示1下的是,如果是360默认系统安全的服务,它肯定不会报不安全,替换闲置的系统安全的服务则通过360的效果要好的多

本文来自: 华夏黑客同盟论坛 本文详细地址:>

//TV类

public class Tv {

public void open(){

Systemoutprintln("打开电视机");

}

public void close(){

Systemoutprintln("关闭电视机");

}

public void search(int x){

Systemoutprintln("您搜索到的是"+x+"号频道");

}

public void ctrlVol(String s){

int vol=10;

if(sequals("+"))

vol++;

if(sequals("-"))

vol--;

Systemoutprintln("当前音量为"+vol);

}

public void changeChannel(int x){

if( x > 29 )

Systemoutprintln("没有该频道");

else

Systemoutprintln("当前"+x+"号频道");

}

public void changeChannel(String s){

int x=0;

if(sequals("+"))

x++;

if(sequals("-"))

x--;

Systemoutprintln("当前"+x+"号频道");

}

}

//Controller遥控器类

public class Controller{

public void openTv(Tv tv){

tvopen();

}

public void closeTv(Tv tv){

tvclose();

}

public void searchTv(Tv tv){

int x=(int)(Mathrandom()30);

tvsearch(x);

}

public void ctrlTvVol(Tv tv){

tvctrlVol("+");

}

public void changeTvChannel(Tv tv){

tvchangeChannel("+");

tvchangeChannel(23);

}

}

摆在我面前的问题就是选择什么语言进行编写咯,我首先考虑了JAVA,首先我从来没写过JAVA的程序,而且IDE装起来很麻烦,而且还是英文的,那更加完全不懂了。然后是C#,很多人都不知道C#可以写Android应用。其实是可以的,但是Android Studio我上次用着卡卡的,印象不是很好,不想用。那还剩下什么选择呢?还有一个:HTML5。 

好了我去装了个Hbuilder: 

 

中文的,很好用,问题在于我也从来没用过javascript,不过这是小问题啦。 

打开Hbuilder,设置一些护眼什么的,然后点左上角[文件]-[新建]-[移动APP]。然后我选了个模板: 

 

嗯,这就是这个程序在手机上执行的时候的样子。然后我模仿着加了一个列表项到indexhtml里面去:

<li id="plus/controllerhtml" onclick="clicked(thisid);">

<span class="item">Controller        <div class="chs">小车遥控器</div>

</span></li>12345

好的,于是这个列表就加了一个选项了。: 

 

继续,在plus文件夹里边添加一个controllerhtml,这就是我们的摇杆所存在的页面。在这个页面上,我们需要一个canvas标签和一个js脚本共同来绘制摇杆:

<!DOCTYPE html><html>

<head>

<meta charset="UTF-8">

<meta name="viewport" content="initial-scale=10, maximum-scale=10, user-scalable=no" />

<meta name="HandheldFriendly" content="true" />

<meta name="apple-mobile-web-app-capable" content="yes" />

<!--<meta name="MobileOptimized" content="320" />-->

<title>小车遥控器</title>

<script type="text/javascript" src="/js/commonjs"></script>

</head>

<body>

<div class="leftjoystick">

<canvas id="joystick" width="120" height="120"></canvas>

<script src="/js/Joystickjs"></script>

</div>

</body></html>12345678910111213141516171819

好了,开始写代码绘制摇杆之前,我先做了两幅图,这样绘制摇杆时候就比较省力气了,效果也比较好。。 

然后经过了一整天来熟悉javascript。我把控制摇杆的js代码捣鼓出来了。放代码咯:

var ji = new Image(); //内摇杆var jo = new Image(); //外摇杆var joystick = documentgetElementById('joystick'); //画板var josize = joystickheight; //外摇杆大小var jisize = josize 06; //内摇杆大小var centerX = josize / 2; //摇杆中心x坐标var centerY = josize / 2; //摇杆中心y坐标windowaddEventListener('load', load, false);var jc = joystickgetContext('2d'); //画布//摇杆头应当移动到的位置var jx = 0,

jy = 0;//加载完成时执行这俩函数jionload = function() {

jcdrawImage(ji, centerX - jisize / 2, centerY - jisize / 2, jisize, jisize); //首次绘制内摇杆}

joonload = function() {

jcdrawImage(jo, centerX - josize / 2, centerY - josize / 2, josize, josize);

}//绘图函数(绘制图形的时候就是用户观察到摇杆动了,所以取名是move)function move() {

jcclearRect(centerX - josize / 2, centerY - josize / 2, josize, josize);//清空画板

jcdrawImage(jo, centerX - josize / 2, centerY - josize / 2, josize, josize);//画底座

jcdrawImage(ji, centerX - jisize / 2 + jx, centerY - jisize / 2 + jy, jisize, jisize);//画摇杆头

requestAnimationFrame(move); //下一次绘图}

jisrc = '/img/joystickinpng';//加载josrc = '/img/joystickoutpng';//加载//页面加载时执行该函数function load() {

documentaddEventListener('touchstart', touch, false);

documentaddEventListener('touchmove', touch, false);

documentaddEventListener('touchend', touch, false);    //加载的时候先把摇杆绘制出来再说

move();    //var effectiveFinger = 0; //当前有效手指

//触摸事件触发函数

function touch(event) {

var event = event || windowevent;        var oInp = documentgetElementById("inp");        switch(eventtype) {            case "touchstart":                //              //判断是否击中摇杆头

//              if(Mathabs(eventtouches[eventidentifier]clientX - 100 - jx) <= 40 &&

//                  Mathabs(eventtouches[eventidentifier]clientY - 100 - jy) <= 40) {

//                  effectiveFinger = eventidentifier; //若是,则将此手指设为有效手指

//              }//这个不知道为啥不能起作用,获取不到eventidentifier。

break;            case "touchend"://手指离开的时候

//若手指离开,那就把内摇杆放中间

jx = 0;

jy = 0;                break;            case "touchmove"://手指移动的时候:

//是否触摸点在摇杆上

if(Mathsqrt(Mathpow(eventtouches[effectiveFinger]clientX - centerX, 2) +                        Mathpow(eventtouches[effectiveFinger]clientY - centerY, 2)) <=

josize / 2 - jisize / 2) {

jx = eventtouches[effectiveFinger]clientX - centerX;

jy = eventtouches[effectiveFinger]clientY - centerY;

} else

//否则计算摇杆最接近的位置

{                    var x = eventtouches[effectiveFinger]clientX,

y = eventtouches[effectiveFinger]clientY,

r = josize / 2-jisize/2;                    var ans=GetPoint(centerX,centerY,r,centerX,centerY,x,y);                    //圆与直线有两个交点,计算出离手指最近的交点

if(Mathsqrt((ans[0]-x)(ans[0]-x)+(ans[1]-y)(ans[1]-y))<Mathsqrt((ans[2]-x)(ans[2]-x)+(ans[3]-y)(ans[3]-y)))

{

jx=ans[0]-centerX;jy=ans[1]-centerY;

}                    else

{

jx=ans[2]-centerX;jy=ans[3]-centerY;

}

}                //move();

eventpreventDefault();//防止页面滑动,取消掉默认的事件

break;

}

}

requestAnimationFrame(move);//开始绘图}//计算圆于直线的交点(这一块好难啊)function GetPoint(cx, cy, r, stx, sty, edx, edy) {

//(x-cx)^2+(y-cy)^2=r^2

//y=kx+b

var k = (edy - sty) / (edx - stx);    var b = edy - k edx;    //(1 + k^2)x^2 - x(2cx -2k(b -cy) ) + cxcx + ( b - cy)(b - cy) - rr = 0

var x1, y1, x2, y2;    var c = cx cx + (b - cy) (b - cy) - r r;    var a = (1 + k k);    var b1 = (2 cx - 2 k (b - cy));    var tmp = Mathsqrt(b1 b1 - 4 a c);

x1 = (b1 + tmp) / (2 a);

y1 = k x1 + b;

x2 = (b1 - tmp) / (2 a);

y2 = k x2 + b;    return [x1,y1,x2,y2];

}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116

这个代码的思路就是,如果手指在底座上,那么就把摇杆头移动到手指下方,如果手指在底座外,那就把摇杆移动到底座离手指最近的部分。嗯,就是这样。

以上就是关于本人是单片机初学求C语言红外遥控解码程序并用数码管显示带注悉全部的内容,包括:本人是单片机初学求C语言红外遥控解码程序并用数码管显示带注悉、易语言怎么编写远程控制啊像灰鸽子的那种!最好有源代码!、急求一个java仿真程序 用面向对象程序设计语言编写“电视机-遥控器”仿真程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10217691.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-06
下一篇 2023-05-06

发表评论

登录后才能评论

评论列表(0条)

保存