Win32汇编学习笔记07.筛选器异常-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net

钢琴

od调试老师给的多媒体钢琴

运行找到Piano的过程函数里去

找到处理WM_KEYDOWN消息的那

下个断点,然后按键断下来在这

  • 分析上图汇编代码:mov eax,dword ptr [ebp+10] 拿wParma
  • lea ecx,dword ptr [eax-41] ,41的ASSCII为A,这里应该是判断是哪个按键做准备
  • cmp ecx,19 19h->25,0~25为26个数,对应26个字母
  • ja imm 大于则不是字母按键,跳出
  • 发出声音功能的函数应该是下面的call <jnp.&oiano_dll.fun_lpayOneSound>
  • 然后我们观察该函数,分析其为C调用约定,传入一个参数,push eax
  • 该函数参数eax的来源是上面的wParma

我们去写一个win32程序去测试一下

RasAsm创建工程MyPiano

相应地方:;=============包起来的是后加入的代码

586
.model flat,stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data
ClassName db "MainWinClass",0
AppName db "Main Window",0
g_szPianoDll db "piano_dll",0
g_szPlayOneSound db "fun_playOneSound",0
g_pfnPlayOneSound dd 0
g_hPianoDll dd 0 .data?
hInstance HINSTANCE ?
CommandLine LPSTR ? .code ; --------------------------------------------------------------------------- start:
;=============
invoke LoadLibrary,offset g_szPianoDll
mov g_hPianoDll,eax
invoke GetProcAddress,g_hPianoDll,offset g_szPlayOneSound
mov g_pfnPlayOneSound,eax
;============= invoke GetModuleHandle, NULL
mov hInstance,eax invoke GetCommandLine
mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd .WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW mov eax,msg.wParam
ret
WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
.elseif uMsg==WM_KEYDOWN
;=============
push wParam
call g_pfnPlayOneSound
add esp,4
;=============
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF xor eax,eax
ret
WndProc endp end start

但是我们发现无论是注入asm和刚刚的这个,都无法让钢琴发出声音,我们在换成 WM_KEYUP和 WM_KEYCHAR 结果跟 WM_KEYDOWN 一样 因此我们打开dll看看其导出函数(之前分析那个函数的所在dll)

猜想可能有所谓的播放环境,可能需要调用其它函数相辅相成

比如需要先调用fun_Create,可能调用时机比较早,我们直接用od调式去对应dll查看名称找该函数。

查看参考

发现只有一个地方式函数调用,我们直接去看看

发现WM_CREATE就调用了,果然如此

因此回到我们的MyPiano的工程中加入对应的,注意要将对应dll及其它可能用到文件都拷贝到工程目录下

值得注意的是fun_Create有一个参数,在上图看出来参数来自esi,可追溯其来源

然后修改为:

.586
.model flat,stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data
ClassName db "MainWinClass",0
AppName db "Main Window",0
g_szPianoDll db "piano_dll",0
g_szPlayOneSound db "fun_playOneSound",0
g_szfun_Create db "fun_Create",0
g_pfnPlayOneSound dd 0
g_pnfun_Create dd 0
g_hPianoDll dd 0 .data?
hInstance HINSTANCE ?
CommandLine LPSTR ? .code ; --------------------------------------------------------------------------- start:
;=============
invoke LoadLibrary,offset g_szPianoDll
mov g_hPianoDll,eax
invoke GetProcAddress,g_hPianoDll,offset g_szPlayOneSound
mov g_pfnPlayOneSound,eax
invoke GetProcAddress,g_hPianoDll,offset g_szfun_Create
mov g_pnfun_Create,eax
;============= invoke GetModuleHandle, NULL
mov hInstance,eax invoke GetCommandLine
mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd .WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW mov eax,msg.wParam
ret
WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
push hWnd
call g_pnfun_Create
add esp,4
.elseif uMsg==WM_KEYDOWN
;=============
push wParam
call g_pfnPlayOneSound
add esp,4
;=============
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF xor eax,eax
ret
WndProc endp end start
  • 接下来探究这个钢琴如何触发使用曲子,即那些文本文件所记录的曲子

去od找读文件相关操作

右键反汇编窗口,选择字符串查找,该软件需要用unicode查找才可

下面这个玩意非常可疑

选中回车到对应位置

插入od功介绍:选中 call 一行右击转到

可以看到调用这个函数的地方

思路回到打开文件对应函数上

点击其中一个转到对应调用处

再起上面那个push再来转到

转到的是下面这个jmp,然后再看sub又是哪里跳过来的呢?

转到下面所示的jg 另外一个mov ecx,dword ptr [ebp+10]是commad消息!!!

我们猜测这里应该有拿资源id的操作

利用vs:文件->打开->文件

选择该exe

情况如下

点开快捷键查看

32772->对应上面我们怀疑是拿资源id那个立即数的8004h,十分巧合?

再去回想之前的转到那

去8004h对应要走的地方去下断点,ctrl+K测试

断点果然下来了

但是并没有播放音乐,我们通过断点处往下走观察发现仅仅只是读了数据而已。

我们可以看它把读的东西放到哪里去了。

再去看文件读写那

有用到了全局变量,往它那些如东西,如果别的地方要用到,肯定也要访问全局变量。

如何看那些地方用到了对应的全局变量?选中,右键->查找参考->地址参考

那么只要用到了该全局变量的地方都列举出来了

我们一个个找对应的读操作里面的情况,找到此处有循环,值得注意一下了!!!

看看它从哪里来的

转到这个jnz,发现还是KeyDown消息触发。又有一个全局变量,去看看它

只有一个1,那么就进去看看

来自于8003,32771h ctrl+j

总结:

  • crtl+num 读文件
  • ctrl+j 开启 在右上角画一个点
  • ctrl+k 关闭 取消右上角画的点
  • 按任意键即可播放文件曲子
.586
.model flat,stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data
ClassName db "MainWinClass",0
AppName db "Main Window",0
g_szDll db "piano_dll.dll",0 ;要加载的 dll
g_szPlay db "fun_playOneSound",0 ;要加在的dll中函数(播放音乐)
g_szCreate db "fun_Create", 0 ;要加在的dll中函数(初始化)
g_pfnCreate dd 0 ;函数地址
g_pfnPlay dd 0 ;函数地址 .data?
hInstance HINSTANCE ? ;
CommandLine LPSTR ? ; .code ; --------------------------------------------------------------------------- start:
invoke GetModuleHandle, NULL
mov hInstance,eax invoke GetCommandLine
mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
LOCAL hDll:HANDLE ;dll句柄 invoke LoadLibrary, offset g_szDll ;动态加载dll
mov hDll, eax ;保存dll句柄 invoke GetProcAddress,eax, offset g_szPlay ;获取函数地址
mov g_pfnPlay, eax ;保存函数地址
invoke GetProcAddress, hDll, offset g_szCreate ;获取函数地址
mov g_pfnCreate, eax ;保存函数地址 mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd .WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW mov eax,msg.wParam
ret
WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
push hWnd ;窗口句柄入栈
call g_pfnCreate ;调用播放初始化函数 (c调用约定)
add esp, 4 ;自己平栈
.elseif uMsg == WM_KEYDOWN
push wParam ;按下的字符入栈
call g_pfnPlay ;调用播放音乐函数 (c调用约定)
add esp, 4 ;自己平栈
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF xor eax,eax
ret
WndProc endp end start

筛选器异常

操作系统有个机制,他会把异常通告给我们应用程序,让我们应用程序来处理,异常机制 windows 系统提供了3种,筛选器异常,SEH 结构化异常,veh 向量异常

筛选器异常是一种最终的异常处理方式,当异常发生时,我们可以在程序启动时,我们可以给程序注册一个异常回调函数当异常发生时,系统就会调这个异常函数,让我们有一次处理的机会.

如果我们要处理筛选器异常哦们需要自己写一个处理的函数,然后把这个函数注册到给操作系统,这样操作系统就知道你要处理筛选器,如果没有注册,那么系统默认不处理筛选器异常

异常派发流程

处于调试状态的派发流程

异常出现时,系统首先给 调试器,调试器不处理的话给 应用程序,,应用程序给 SEH, SEH不处理,会再给调试器,调试器不处理优惠给应用程序,应用程序此时会给筛选器,  筛选器也不处理就直接给操作系统了,操作系统此时必须处理,操作系统处理方式就是关闭程序 ,

处于非调试状态的派发流程

异常出现时,系统首先给  SEH, SEH不处理,就会给筛选器,筛选器也不处理就直接给操作系统了,操作系统此时必须处理,操作系统处理方式就是关闭程序

筛选器是最后一次应用程序处理异常的机会,因此被称为最终异常

注册筛选器 SetUnhandledExceptionFilter

LPTOP LEVEL EXCEPTION FILTER SETUNHANDLEDEXCEPTIONFILTER(

LPTOPLEVELEXCEPTIONFILTER

LPTOP LEVEL EXCEPTION FILTER

参数 : 函数指针 : 自己注册的函数函数指针 返回值 函数指针: 之前注册的函数指针

声明

LONG SetUnhandledExceptionFilter( STRUCT _EXCEPTION_POINTERS *ExceptionInfo );

结构体 EXCEPTION_POINTERS

第一个成员: 异常记录 (异常信息)

第二个成员: 环境记录 (寄存器环境)

异常记录: EXCEPTION_RECORD

成员: 异常码 (异常种类)

标志(不用管)
异常嵌套 (处理异常过程中出现了异常)
异常产生的地址 (EIP)
产生异常的: 参数数量
异常发生时的操作, 0 是 读  1是写 ,第二个是访问异常的地址(意思是你读或写哪个地址时发生了异常)
.586
.model flat,stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data
g_szTitle db "提示",0
g_szText db "异常来了",0 .data?
hInstance HINSTANCE ?
CommandLine LPSTR ? .code ;异常回调函数 参数:结构体指针
MyUnhandledExceptionFilter proc pExceptPointer:ptr EXCEPTION_POINTERS invoke MessageBox, NULL, offset g_szText, offset g_szTitle, MB_OK ;--------搭配 EXCEPTION_CONTINUE_EXECUTION,不然无法退出程序---------------
;---继续执行,即从56行继续执行,又报异常继续回到56行异常处,导致死循环,因此需要跳过56行代码 mov esi, pExceptPointer ;获取出现异常的地址
assume esi:ptr EXCEPTION_POINTERS ;地址类型类型强转
mov esi, [esi].ContextRecord ;获取出现异常环境记录
assume esi:ptr CONTEXT ;地址类型类型强转
add [esi].regEip, 2 ;跳过出现异常的代码,异常代码地址+2
assume esi:nothing ;还原类型
;----------------------------- ;mov eax, EXCEPTION_EXECUTE_HANDLER; - 异常已处理,结束进程 ;mov eax, EXCEPTION_CONTINUE_EXECUTION; -异常已经处理,可以继续执行代码 mov eax, EXCEPTION_CONTINUE_SEARCH; - 异常我不处理,交给系统处理,跟第一种区别不大 ret
MyUnhandledExceptionFilter endp start:
;注册异常回调函数
invoke SetUnhandledExceptionFilter,offset MyUnhandledExceptionFilter mov eax, 1212h
mov [eax], eax ;因为1212属于不可访问地址,因此会出现异常 invoke MessageBox, NULL, offset g_szText, offset g_szTitle, MB_OK
invoke ExitProcess,0
end start

作业

1. 带作弊功能的钢琴

大键盘1是开启

大键盘2是关闭

大键盘3是读取文件

先读取文件 然后再开启。

.586
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include msvcrt.inc
include shlwapi.inc includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
includelib msvcrt.lib
includelib shlwapi.lib WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .data
ClassName db "MainWinClass",0
AppName db "Main Window",0
g_szDll db "piano_dll.dll",0
g_szPlay db "fun_playOneSound",0
g_szCreate db "fun_Create", 0
g_pfnCreate dd 0
g_pfnPlay dd 0
g_TestCut dd 0
g_TestOpenWin db "打开成功", 0
g_TestCloseWin db "关闭成功", 0 g_TestFmt db"1.txt",0
g_wFileCode dd 0
g_szFileMode db "r", 0
g_FileTest db 255 dup(0),0
g_TestChar db 0 g_TestBuf db 0
g_TestFlag db 0 .data?
hInstance HINSTANCE ?
CommandLine LPSTR ? .code start:
invoke GetModuleHandle, NULL
mov hInstance,eax invoke GetCommandLine
mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
LOCAL hDll:HANDLE invoke LoadLibrary, offset g_szDll
mov hDll, eax invoke GetProcAddress,eax, offset g_szPlay
mov g_pfnPlay, eax
invoke GetProcAddress, hDll, offset g_szCreate
mov g_pfnCreate, eax mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd .WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW mov eax,msg.wParam
ret
WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL .ELSEIF uMsg==WM_CREATE push hWnd
call g_pfnCreate
add esp, 4
.elseif uMsg == WM_KEYDOWN lea eax,g_TestFlag .if word ptr[eax] == 0
.if wParam =="1" invoke MessageBox,NULL,NULL,offset g_TestOpenWin,MB_OK
lea eax,g_TestFlag
mov word ptr[eax],1 .elseif wParam == "2" invoke MessageBox,NULL,NULL,offset g_TestCloseWin,MB_OK lea eax,g_TestFlag
mov word ptr[eax],0
.elseif wParam == "3" ;载入文件 ;打开文件
invoke crt_fopen,offset g_TestFmt,offset g_szFileMode
mov g_wFileCode,eax
;读文件
invoke crt_fgets,offset g_FileTest,255, g_wFileCode .else push wParam
call g_pfnPlay
add esp, 4 .endif .else .if wParam != "2"
lea ebx, g_FileTest
mov wParam, ebx push wParam
call g_pfnPlay
add esp, 4 .else
invoke MessageBox,NULL,NULL,offset g_TestCloseWin,MB_OK
lea eax,g_TestFlag
mov word ptr[eax],0 .endif .endif .ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF xor eax,eax
ret
WndProc endp end start
  1. 在筛选器异常处理中dump程序 MiniDumpWrite

Win32汇编学习笔记07.筛选器异常的更多相关文章

  1. 异常处理第一讲(SEH),筛选器异常,以及__asm的扩展,寄存器注入简介

    异常处理第一讲(SSH),筛选器异常,以及__asm的扩展 博客园IBinary原创  博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 一丶__Asm的 ...

  2. 学习笔记 07 --- JUC集合

    学习笔记 07 --- JUC集合 在讲JUC集合之前我们先总结一下Java的集合框架,主要包含Collection集合和Map类.Collection集合又能够划分为LIst和Set. 1. Lis ...

  3. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

    机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析 关键字:Apriori.关联规则挖掘.频繁项集作者:米仓山下时间:2018 ...

  4. 汇编学习笔记(11)int指令和端口

    格式 int指令也是一种内中断指令,int指令的格式为int n,n是中断类型码.也就是说,使用int指令可以调用任意的中断例程,例如我们可以显示的调用0号中断例程,还记得在汇编学习笔记(10)中我们 ...

  5. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  6. java学习笔记13--比较器(Comparable、Comparator)

    java学习笔记13--比较器(Comparable.Comparator) 分类: JAVA 2013-05-20 23:20 3296人阅读 评论(0) 收藏 举报 Comparable接口的作用 ...

  7. Win32汇编学习(4):绘制文本

    这次,我们将学习如何在窗口的客户区"绘制"字符串.我们还将学习关于"设备环境"的概念. 理论: "绘制"字符串 Windows 中的文本是一 ...

  8. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  9. matlab学习笔记7-定时器

    一起来学matlab-matlab学习笔记7-定时器 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张老师的书籍,让 ...

  10. JavaSE学习笔记(6)---异常

    JavaSE学习笔记(6)---异常 ​ 软件程序在运行过程中,非常可能遇到问题,我们称之为异常,英文是:Exception,意思是例外.遇到这些例外情况,或者叫异常,我们怎么让写的程序做出合理的处理 ...

随机推荐

  1. PHP站点及mysql常用操作

    1.mysql查询表里面重复数据 SELECT * FROM 表名xxxx a WHERE ((SELECT COUNT(*) FROM 表名xxxx WHERE title = a.title) & ...

  2. ubuntu20.04使用EasyConnect

    起因:BUAA校外访问内网vpn的客户端 用的学校vpn内下载的deb包EasyConnect_x64_7_6_7_3.deb,就直接sudo apt install安装了,之后应用的目录在/usr/ ...

  3. CNVD挖掘思路

    CNVD挖掘思路 CNVD获取条件 首先,先来了解一下目前cnvd发证资格 1.事件型 事件型漏洞必须是三大运营商(移动.联通.电信)的中高危漏洞,或者党政机关.重要行业单位.科研院所.重要企事业单位 ...

  4. 业余无线电爱好者,自制天线比较容易上手天线“莫克森天线”Moxon

    本文仅作为笔记分享,如有疑问可以留言交流. 莫克森天线尺寸计算软件:Moxon rectangle 高手门做的成品,参考资料: 英文文献资料:

  5. 最新活动 ISS 国际空间站 MAI-75 SSTV活动计划于2020年8月4日至5日

    MAI-75  SSTV活动计划于2020年8月4日和5日举行 8月3日至9日这一周的最后宇航员时间表最近公布了,它显示了定于8月4日和5日进行的MAI-75活动.这是在Space X Demo-2脱 ...

  6. 【Python】解决“Tk_GetPixmap: Error from CreateDIBSection”闪退问题

    解决Python使用Tkinter的Notebook切换标签时出现的"Tk_GetPixmap: Error from CreateDIBSection 操作成功完成"闪退问题 零 ...

  7. Oracle SQL%ROWCOUNT

    SQL%ROWCOUNT 用于记录受影响的行数, 必须紧跟在一个新增/修改/删除类语句后. 当执行多条修改语句时, 按照 sql%rowcount 之前执行的最后一条语句受影响行数为准. 应用场景 可 ...

  8. Redis 应用场景之短信验证码

    应用场景 以 OSChina 账号注册 为例...讲错了请留言批评指正... 逻辑场景 用户操作: 用户输入手机号, 然后点击获取验证码. 前端逻辑: ajax 发起请求, 参数带上手机号. 后端逻辑 ...

  9. 离线版nrfutil工具安装方法

    简介 nrfutil是Nordic提供的命令行工具集.支持以下功能: 基于Jlink的固件烧录.读取.flash擦除.recover 基于MCUBOOT的固件升级(DFU) 基于nRF5 bootlo ...

  10. 张高兴的大模型开发实战:(四)使用 LangGraph 实现多智能体应用

    目录 环境搭建与配置 定义智能体 加载模型 提取关键词 生成回答 连接智能体 定义图的状态 定义节点方法 根据指令路由 生成回答 文件处理 提取关键词 网络搜索 定义图的结构 运行图 运行指南 在控制 ...