- 博客(49)
- 收藏
- 关注
原创 Duilib_CEF桌面软件实战之Duilib嵌入CEF
本文将CEF嵌入到已集成Duilib的Win32程序中。首先将编译好的CEF文件拷贝到项目目录,配置包含路径和库目录。接着创建Cef_App和Cef_Handler类继承CEF相关基类,实现必要的回调函数。然后创建CCefBrowserUI控件类继承Duilib的CControlUI,实现浏览器控件的创建和显示功能。在XML界面中添加cefbrowser控件,并重载CreateControl方法关联控件。最后处理了编译错误和运行崩溃问题,通过添加command_line->AppendSwitch(&
2025-11-13 10:10:08
1622
原创 Duilib_CEF桌面软件实战之Duilib编译与第一个界面程序
Duilib是Windows平台下轻量级的DirectUI开源库,可用于商业软件开发。它通过XML实现界面定制,支持换肤、透明等功能。本文介绍了使用Troy维护版Duilib的开发流程:包括项目配置、创建继承WindowImplBase的窗口类、设置资源路径、编写基础XML界面文件等步骤,最终实现了一个800×600的天蓝色窗口。该教程详细说明了从环境搭建到第一个界面完成的完整过程。
2025-11-07 15:38:07
580
原创 Duilib_CEF桌面软件实战之CEF入口函数
该文章详细介绍了CEF(Chromium Embedded Framework)应用程序的启动流程。主要逻辑包括:1) 初始化CEF参数;2) 通过CefExecuteProcess区分主进程与子进程;3) 主进程进行CEF初始化(CefInitialize);4) 启动消息循环(CefRunMessageLoop);5) 退出时释放资源(CefShutdown)。文章还解释了进程启动原理,如何区分主/子进程,以及各参数的作用。最后CEF消息循环的工作原理,即CefRunMessageLoop会阻塞执行
2025-11-06 10:44:40
1062
原创 Duilib_CEF桌面软件实战之零基础快速编译CEF
摘要:本文介绍了CEF(Chromium嵌入式框架)的编译和使用方法。首先从官网下载稳定版CEF,然后使用CMake工具配置并生成VS2022工程。编译cefsimple工程后,通过修改simple_app.cc文件中的URL地址,成功将默认主页从Google改为优快云。文中详细说明了从下载到修改代码的完整流程,并提示需要注意编译器版本要求。
2025-11-04 11:33:18
552
原创 C语言基础之结构体
/ 方式1:先定义结构体类型,再声明变量int age;// 方式2:定义类型的同时声明变量int x;int y;} p1, p2;// 声明两个变量p1, p2// 方式3:使用typedef定义别名} Book;// 声明结构体变量p1.x = 3;p1.y = 4;Book book1;return 0;
2025-10-28 11:06:06
154
原创 C语言基础之参数和指针
从结果可以看出x与y的值在经过函数交换后并没有发生改变。那如果想经过函数后也改变他们的值该如何操作呢?(pass by value),这意味着函数接收到的是参数的副本。使用指针作为参数可以实现。的效果,让函数能够修改调用者的数据。在C语言中,参数传递默认是。未执行函数前内存数据。
2025-10-27 15:25:57
234
原创 C语言基础之常量和指针
但可以直接修改变量的值(如果变量不是const)竟然不能通过这种方式修改,那我们应该怎么修改呢?如果我们想把p指针指向其他地址会发生什么情况呢?const 数据类型 *const 指针变量名;const 数据类型 *指针变量名;数据类型 *const 指针变量名;指针本身是常量,不能指向其他地址。指针本身是常量,不能指向其他地址。不能通过指针修改所指向的值。可以通过指针修改所指向的值。不能通过指针修改所指向的值。在左边:指向的内容是常量。指针可以指向不同的地址。在右边:指针本身是常量。
2025-10-27 14:02:59
205
原创 C语言基础之指针和二维数组
ptr_arr[]存储的结果我们还能理解,因为它里面是指针,但是ptr_arr[][]取出的数据就有点莫名其妙了,它是怎么实现的呢?2. ptr_arr[0][1] 访问地址 0x1000 + 1*sizeof(int) = 0x1004。2. ptr_arr[1][2] 访问地址 0x1008 + 2*sizeof(int) = 0x1010。2. ptr_arr[2][3] 访问地址 0x1014 + 3*sizeof(int) = 0x1020。3. 从地址 0x1004 读取值 2。
2025-10-23 14:22:54
695
原创 Day8C语言前期阶段算法之归并排序
两个有序的两张牌合并成有序的四张牌。两堆单张牌合并成有序的两张牌。继续分,直到每堆只有一张牌。继续合并,直到整副牌有序。
2025-10-22 15:33:34
130
原创 Day7C语言前期阶段算法之选择排序
每次从待排序的数据中找出最小(或最大)的元素,放到已排序序列的末尾。在[64,25,12,22,11]中找到最小值11。在[25,64]中找到最小值25(已在正确位置)从剩下的牌中再找出最小的,放在刚才那张的右边。在[25,12,22,64]中找到最小值12。无需交换 → [11, 12, 22,在[25,22,64]中找到最小值22。交换25和22 → [11, 12,从所有牌中找出最小的,放在最左边。交换25和12 → [11,交换64和11 → [重复直到所有牌都排好。
2025-10-21 15:32:22
328
原创 Day7C语言前期阶段项目之学生成绩管理系统
一个简单的学生成绩统计程序,主要功能包括:输入学生人数和成绩计算平均分找出最高分和最低分显示统计结果和所有成绩int n, i;printf("请输入学生人数(最多%d人): ", MAX_STUDENTS);printf("输入错误!\n");return 1;// 输入成绩for (i = 0;i < n;i++) {printf("请输入第%d个学生的成绩: ", i + 1);// 计算平均分// 找最高分和最低分for (i = 1;i < n;
2025-10-21 10:26:07
147
原创 C语言前期阶段练习作业规划
它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
2025-10-17 14:27:38
428
原创 C语言基础之初识函数
你可以把函数想象成一个“加工厂”或“黑盒子”。输入(参数):你给工厂一些原材料。处理(函数体):工厂内部按照固定的流程对原材料进行加工。输出(返回值):工厂生产出成品给你。在编程中,函数是一段为了完成特定任务而封装起来的、可重复使用的代码块。为什么要使用函数?代码复用:避免重复编写相同的代码,写一次,调用多次。模块化:将复杂的大问题分解成若干个小问题,使程序结构清晰,易于理解和维护。提高效率:多人协作开发时,可以分工编写不同的函数。返回值类型 函数名(参数列表) {// 函数体(执行语句)
2025-10-17 11:18:46
520
原创 C语言基础数组作业(冒泡算法)
是 → 交换 → [3,5,8,1]// j=1: [3,5,8,1] → 5>8?是 → 交换 → [3,5,1,8]// j=0: [3,5,1,8] → 3>5?是 → 交换 → [3,1,5,8]// j=0: [3,1,5,8] → 3>1?是 → 交换 → [1,3,5,8]// 初始数组: [5, 3, 8, 1]
2025-10-16 17:02:27
809
原创 Day4 if语句课后作业
摘要:本文展示了一个简单的C语言登录验证系统,使用strcmp函数比较用户名和密码。系统允许3次尝试机会,验证成功则显示"登录成功",失败达到3次则锁定账户。文章还详细解释了strcmp函数的用法:它比较两个以'\0'结尾的字符串,返回0表示相同,正/负值表示ASCII码差异。该系统实现了基本的登录验证功能,但存在安全隐患(如硬编码密码)。
2025-10-15 10:58:47
169
原创 C语言基础之IF语句
前几节课中我们写过一个简单的密码验证系统,现在学了这么多语句,把它完善一下吧!// 条件为真时执行的代码块。好了,到这里if语句也学得差不多了。// 条件为真时执行的代码。// 条件为假时执行的代码。} else if (条件2) {} else if (条件3) {// 所有条件都为假时执行。// 条件1为真时执行。// 条件2为真时执行。// 条件3为真时执行。赋值运算符 vs 比较运算符。if (条件表达式) {if (条件表达式) {if (条件1) {
2025-10-14 14:54:04
307
原创 DAY3switch语句和分支嵌套课后作业
程序是正常的,所以这道题就一个错误点。也是新手朋友经常犯错的哦。利用循环和switch语句写一个菜单驱动程序。从错误提示我们可以知道。
2025-10-14 11:20:32
227
原创 Day2循环语句课后练习
好了,循环课后作业已经完成,大家也可以用各种姿势打印99乘法表哦,希望有兴趣的朋友也动动手!利用for循环写出99乘法表。(这道题对于新手朋友可能有点难,因为需要嵌套循环!利用do...while写出一个简单的用户输入密码验证系统场景。这个系统虽然简陋但是对于新手的我们是不是还是挺有意思的!使用3种循环计算1+2+3...+100的值。
2025-10-13 14:56:58
143
原创 Day1数据类型与变量作业
相传古印度宰相达依尔发明了国际象棋,国王舍罕王想要奖赏他。宰相说:请在棋盘的第1个格子放1粒麦子,第2格放2粒,第3格放4粒,以后每一格都是前一格的2倍,直到放满64个格子。国王以为这个要求很简单,但实际计算后发现,全世界的麦子都不够!总麦粒数:S = 2⁰ + 2¹ + 2² + ... + 2⁶³ = 2⁶⁴ - 1。好了,作业终于完成了,聪明的你肯定还有更好的方法吧,快点试试吧!是不是使用微软提供的函数比自己写方便多了。第1格:2⁰ = 1粒。第2格:2¹ = 2粒。第3格:2² = 4粒。
2025-10-11 14:05:36
363
原创 C语言基础之循环语句(while do...while for)
什么是循环结构?在什么场景需要使用循环?在编程中当我们需要重复执行同一段代码很多次甚至无数次时,就可以考虑使用循环结构来解决。代码结构非常简单。只要表达式的值为真,那么就会不断执行循环体里边的代码块。do...while循环语句与while循环语句类似。do循环体}while (表达式);重点: while 是先判断表达式,如果表达式结果为真,才执行循环体里边的内容;而 do…while 则相反,先执行循环体的内容再判断表达式是否为真。
2025-10-11 10:42:01
497
原创 C语言基础之数据类型与变量
本文介绍了C语言基本数据类型(整型/浮点型/字符型)及其长度判断方法,强调sizeof是运算符而非函数。通过示例代码讲解了变量声明、初始化与修改,以及const和#define两种常量定义方式。最后提出两个编程练习:1)计算1²+2³...+6⁷的幂次和;2)计算国际象棋64格麦粒总数(需用long long类型),指出该问题会超出实际小麦总量。全文涵盖数据类型、变量常量、运算符等基础概念,并给出实际应用场景。
2025-10-10 15:26:46
458
原创 C语言新手入门笔记
作者将把C语言的知识要点,以及自己在工作开发中心得体会以文章形式发表,希望能帮助更多的新手朋友们更好的掌握C/C++开发,也非常希望朋友提出更多宝贵意见,有什么不懂的也可以留言咨询我。
2025-10-10 11:08:16
587
原创 内存管理之物理内存
3.MmNumberOfphysicalPages*4KB 获取当前物理内存总字节数。2.MmNumberOfphysicalPages描述了当前总共物理页数。1.CPU(INTEL与AMD)规定一个物理页大小为4KB。bff7e 转化为十进制 786302。
2024-11-25 11:27:09
271
原创 内存管理之应用层API讲解
以 MEM_RESERVE申请内存,系统不会分配物理地址,所以程序执行写操作会崩溃。使用VirtualProtect修改页属性,对应就是修改内核中页的属性位。当修改成 MEM_COMMIT提交的时候就可以修改该内存。
2024-11-21 14:34:16
334
原创 内核对象之私有句柄表
第1位继承位,是否继承父进程句柄(注入shellcode到白名单进程,白名单进程中执行OpenProcess(PROCESS_ALL_ACCESS,TRUE,保护ID),打开句柄后CreateProces执行自己进程继承打开的句柄。4.OBJECT_header->TypeIndex对应类型索引表(ObTypeInedxTable)当中的索引,其值指向OBJECT_TYPE可以通过Name来判断所属内核对象类型,通过HANDLE在进程私有句柄中找到对应内核对象。全局句柄表与私有句柄表。
2024-11-18 15:01:21
512
原创 内核对象之全局句柄表
1.把PID除以4(固定计算方式)2744/4 = 686超过了512所以在第一张表中(从0开始计算)0x8d404000中存储的是_HANDLE_TABLE_ENTRY对象总共4096/8=512。3)_HANDLE_TABLE.TableCode才是真正存数据的表格。2)PspCidTable存储的数据类型为_HANDLE_TABLE。2.把计算数据转换成16进制(windbg都是用16进制计算)1.把PID除以4(固定计算方式)564/4 = 141。5)计算第一种00类型的进程句柄在表中的位置。
2024-11-14 16:14:45
689
原创 内核对象之句柄结构
该对象在进程对象/线程对象前0x18偏移 = EPROCESS/ETHREAD - 0x18。第二步:从函数ObGetObjectType中得到对象类型全局表,该表目前未导出。第三步:查看_OBJECT_HEADER.TypeIndex在该表中对应的位置。第一步:获取_OBJECT_HEADER.TypeIndex。第四步:查看_OBJECT_TYPE对应数据。
2024-11-14 11:21:26
366
原创 逆向KiInitializeUserApc
5)把KTRAP_FRAME结构中的段选择子修改成RING3数据。把上面申请的内存赋值到KTRAP_FRAME.HardwareEsp作为RING3新的堆栈,修改KTRAP_FRAME._Eip指向。2)初始化内存,这段内存结构可以从下面的函数KeContextFromKframes判断出是Context结构,1)检测_KTRAP_FRAME.EFlages中的VM标志判断是否为虚拟x86环境。4)把空出0x10个字节,开始循环拷贝Context结构到该内存中。6)把参数赋值到空出的0x10个字节中。
2024-11-12 10:55:30
428
原创 KiDeliverApc逆向之用户APC执行流程
判断UserApcPending 是否为1,当UserApcPending = 1时提升IRQL等级,获取ApcQueueLock锁准备开始工作。判断用户APC函数是否为空。在KiDeliverApc函数中用户APC执行过程与内核APC执行流程差不多。2)自旋后取出用户APC链表且该链表指向KAPC->Apc.ListEntry。1)当内核APC全部完成之后执行用户APC,所以内核APC优先于用户APC。3)保存数据到临时变量中,断链,设置KAPC.Inserted = 0。
2024-11-12 10:25:52
391
原创 KiDeliverApc逆向之内核APC执行流程
4)等待自旋完成,取出内核APC链表且该链表指向_KAPC->APCListEntry 再次设置线程ApcState.KernelApcPending = 0,保存数据到临时变量中。1)内核APC不需要切换环境所以TARP_FRAME为空,设置线程ApcState.KernelApcPending = 0。5)判断KernelApcInProgress是否为0,所以内核APC执行KernelApcInProgress = 0。断链,设置KAPC.Inserted = 0,释放锁。
2024-11-11 15:21:45
443
原创 线程之ETHREAD/KTHREAD
线程对应结构:线程一定是运行在某个进程中(R3程序默认运行在创建线程的进程中,R0如果不指定进程默认运行在system进程中)内核线程堆栈 KTRAP_FRAME - KTSS.ESP0提供线程运行在CPU核心上,假如CPU只有一个核,也就意味着当前操作系统同时最多可以运行一条线程,通过不停切换线程 实现并行。进程核心为CR3,通过CR3可以找到当前进程下所有数据,CPU没有进程概念,当一个进程下所有线程都销毁时,操作系统会释放进程。查找线程。
2024-11-01 10:48:03
961
原创 线程之KiFindReadyThread逆向
获取核心上的就绪位--->找到对应_KPRCB.DispatcherReadyListHead--->获取kthread.waitlistentry--->-74h得到线程结构-->判断线程亲核性相同则移除链表中该线程准备执行。
2024-10-30 16:19:31
540
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅