|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
mysql使用内部操作字符集gbk来进行操作,即执行"SELECT*FROMtestWHEREname=xxxor1=1/*LIMIT1";从而注入成功一个例子
这一章,我们要把我们已学的常识汇合起来。详细来说,我们来写一个利用ODBCAPIs的程序.为复杂起见,这个程序中我利用Microsoft的Access数据库(MicrosoftAccess97).
下载例子源程序.
注重:假如你利用的windows.inc是1.18及其以下版本,在入手下手编译之前要修正个中的一个小bug.在windows.inc中查找"SQL_NULL_HANDLE",将失掉上面这行:
SQL_NULL_HANDLEequ0L
将0前面的"L"删除,象如许:
SQL_NULL_HANDLEequ0
这个程序是一个基于对话框的程序,有一个复杂的菜单.当用户选择"connect"时,它将试图毗连test.mdb数据库,假如毗连乐成,将显现由ODBC驱动程序前往的完全毗连字符串.接上去,用户可选择"ViewAllRecords"命令,程序会利用listviewcontrol来显现数据库中的一切数据.用户还能够选择"Query"命令来查询特定的纪录.例子程序将会显现一个小对话框提醒用户输出想找的人名.当用户按下OK钮或回车键,程序将实行一个查询来查找切合前提的纪录.当用户完成对数据库的操纵时,能够选择"disconnect"命令与数据库断开毗连.
如今看一下源程序:
.386.modelflat,stdcallincludemasm32includewindows.incincludemasm32includekernel32.incincludemasm32includeodbc32.incincludemasm32includecomctl32.incincludemasm32includeuser32.incincludelibmasm32libodbc32.libincludelibmasm32libcomctl32.libincludelibmasm32libkernel32.libincludelibmasm32libuser32.libIDD_MAINDLGequ101IDR_MAINMENUequ102IDC_DATALISTequ1000IDM_CONNECTequ40001IDM_DISCONNECTequ40002IDM_QUERYequ40003IDC_NAMEequ1000IDC_OKequ1001IDC_CANCELequ1002IDM_CUSTOMQUERYequ40004IDD_QUERYDLGequ102DlgProcprotohDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORDQueryProcprotohDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORDSwitchMenuStateproto:DWORDODBCConnectproto:DWORDODBCDisconnectproto:DWORDRunQueryproto:DWORD.data?hInstancedd?hEnvdd?hConndd?hStmtdd?Conndb256dup(?)StrLendd?hMenudd?;主菜单句柄hListdd?;listviewcontrol句柄TheNamedb26dup(?)TheSurnamedb26dup(?)TelNodb21dup(?)NameLengthdd?SurnameLengthdd?TelNoLengthdd?SearchNamedb26dup(?)ProgPathdb256dup(?)ConnectStringdb1024dup(?).dataSQLStatementdb"select*frommain",0WhereStatementdb"wherename=?",0strConnectdb"DRIVER={MicrosoftAccessDriver(*.mdb)};DBQ=",0DBNamedb"test.mdb",0ConnectCaptiondb"CompleteConnectionString",0Disconnectdb"Disconnectsuccessful",0AppNamedb"ODBCTest",0AllocEnvFaildb"Environmenthandleallocationfailed",0AllocConnFaildb"Connectionhandleallocationfailed",0SetAttrFaildb"CannotsetdesiredODBCversion",0NoDatadb"Youmusttypethenameintheeditbox",0ExecuteFaildb"ExecutionofSQLstatementfailed",0ConnFaildb"Connectionattemptfailed",0AllocStmtFaildb"Statementhandleallocationfailed",0Heading1db"Name",0Heading2db"Surname",0Heading3db"TelephoneNo.",0.codestart:invokeGetModuleHandle,NULLmovhInstance,eaxcallGetProgramPathinvokeDialogBoxParam,hInstance,IDD_MAINDLG,0,addrDlgProc,0invokeExitProcess,eaxinvokeInitCommonControlsDlgProcprochDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD.ifuMsg==WM_INITDIALOGinvokeGetMenu,hDlgmovhMenu,eaxinvokeGetDlgItem,hDlg,IDC_DATALISTmovhList,eaxcallInsertColumn.elseifuMsg==WM_CLOSEinvokeGetMenuState,hMenu,IDM_CONNECT,MF_BYCOMMAND.ifeax==MF_GRAYEDinvokeODBCDisconnect,hDlg.endifinvokeEndDialog,hDlg,0.elseifuMsg==WM_COMMAND.iflParam==0moveax,wParam.ifax==IDM_CONNECTinvokeODBCConnect,hDlg.elseifax==IDM_DISCONNECTinvokeODBCDisconnect,hDlg.elseifax==IDM_QUERYinvokeRunQuery,hDlg.elseifax==IDM_CUSTOMQUERYinvokeDialogBoxParam,hInstance,IDD_QUERYDLG,hDlg,addrQueryProc,0.endif.endif.elsemoveax,FALSEret.endifmoveax,TRUEretDlgProcendpGetProgramPathprocinvokeGetModuleFileName,NULL,addrProgPath,sizeofProgPathstdmovedi,offsetProgPathaddedi,sizeofProgPath-1moval,""movecx,sizeofProgPathrepnescasbcldmovbyteptr[edi+2],0retGetProgramPathendpSwitchMenuStateprocFlag:DWORD.ifFlag==TRUEinvokeEnableMenuItem,hMenu,IDM_CONNECT,MF_GRAYEDinvokeEnableMenuItem,hMenu,IDM_DISCONNECT,MF_ENABLEDinvokeEnableMenuItem,hMenu,IDM_QUERY,MF_ENABLEDinvokeEnableMenuItem,hMenu,IDM_CUSTOMQUERY,MF_ENABLED.elseinvokeEnableMenuItem,hMenu,IDM_CONNECT,MF_ENABLEDinvokeEnableMenuItem,hMenu,IDM_DISCONNECT,MF_GRAYEDinvokeEnableMenuItem,hMenu,IDM_QUERY,MF_GRAYEDinvokeEnableMenuItem,hMenu,IDM_CUSTOMQUERY,MF_GRAYED.endifretSwitchMenuStateendpODBCConnectprochDlg:DWORDinvokeSQLAllocHandle,SQL_HANDLE_ENV,SQL_NULL_HANDLE,addrhEnv.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokeSQLSetEnvAttr,hEnv,SQL_ATTR_ODBC_VERSION,SQL_OV_ODBC3,0.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokeSQLAllocHandle,SQL_HANDLE_DBC,hEnv,addrhConn.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokelstrcpy,addrConnectString,addrstrConnectinvokelstrcat,addrConnectString,addrProgPathinvokelstrcat,addrConnectString,addrDBNameinvokeSQLDriverConnect,hConn,hDlg,addrConnectString,sizeofConnectString,addrConn,sizeofConn,addrStrLen,SQL_DRIVER_COMPLETE.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokeSwitchMenuState,TRUEinvokeMessageBox,hDlg,addrConn,addrConnectCaption,MB_OK+MB_ICONINFORMATION.elseinvokeSQLFreeHandle,SQL_HANDLE_DBC,hConninvokeSQLFreeHandle,SQL_HANDLE_ENV,hEnvinvokeMessageBox,hDlg,addrConnFail,addrAppName,MB_OK+MB_ICONERROR.endif.elseinvokeSQLFreeHandle,SQL_HANDLE_ENV,hEnvinvokeMessageBox,hDlg,addrAllocConnFail,addrAppName,MB_OK+MB_ICONERROR.endif.elseinvokeSQLFreeHandle,SQL_HANDLE_ENV,hEnvinvokeMessageBox,hDlg,addrSetAttrFail,addrAppName,MB_OK+MB_ICONERROR.endif.elseinvokeMessageBox,hDlg,addrAllocEnvFail,addrAppName,MB_OK+MB_ICONERROR.endifretODBCConnectendpODBCDisconnectprochDlg:DWORDinvokeSQLDisconnect,hConninvokeSQLFreeHandle,SQL_HANDLE_DBC,hConninvokeSQLFreeHandle,SQL_HANDLE_ENV,hEnvinvokeSwitchMenuState,FALSEinvokeShowWindow,hList,SW_HIDEinvokeMessageBox,hDlg,addrDisconnect,addrAppName,MB_OK+MB_ICONINFORMATIONretODBCDisconnectendpInsertColumnprocLOCALlvc:LV_COLUMNmovlvc.imask,LVCF_TEXT+LVCF_WIDTHmovlvc.pszText,offsetHeading1movlvc.lx,150invokeSendMessage,hList,LVM_INSERTCOLUMN,0,addrlvcmovlvc.pszText,offsetHeading2invokeSendMessage,hList,LVM_INSERTCOLUMN,1,addrlvcmovlvc.pszText,offsetHeading3invokeSendMessage,hList,LVM_INSERTCOLUMN,3,addrlvcretInsertColumnendpFillDataprocLOCALlvi:LV_ITEMLOCALrow:DWORDinvokeSQLBindCol,hStmt,1,SQL_C_CHAR,addrTheName,sizeofTheName,addrNameLengthinvokeSQLBindCol,hStmt,2,SQL_C_CHAR,addrTheSurname,sizeofTheSurname,addrSurnameLengthinvokeSQLBindCol,hStmt,3,SQL_C_CHAR,addrTelNo,sizeofTelNo,addrTelNoLengthmovrow,0.whileTRUEmovbyteptrds:[TheName],0movbyteptrds:[TheSurname],0movbyteptrds:[TelNo],0invokeSQLFetch,hStmt.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOmovlvi.imask,LVIF_TEXT+LVIF_PARAMpushrowpoplvi.iItemmovlvi.iSubItem,0movlvi.pszText,offsetTheNamepushrowpoplvi.lParaminvokeSendMessage,hList,LVM_INSERTITEM,0,addrlvimovlvi.imask,LVIF_TEXTinclvi.iSubItemmovlvi.pszText,offsetTheSurnameinvokeSendMessage,hList,LVM_SETITEM,0,addrlviinclvi.iSubItemmovlvi.pszText,offsetTelNoinvokeSendMessage,hList,LVM_SETITEM,0,addrlviincrow.else.break.endif.endwretFillDataendpRunQueryprochDlg:DWORDinvokeShowWindow,hList,SW_SHOWinvokeSendMessage,hList,LVM_DELETEALLITEMS,0,0invokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokeSQLExecDirect,hStmt,addrSQLStatement,sizeofSQLStatement.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokeFillData.elseinvokeShowWindow,hList,SW_HIDEinvokeMessageBox,hDlg,addrExecuteFail,addrAppName,MB_OK+MB_ICONERROR.endifinvokeSQLCloseCursor,hStmtinvokeSQLFreeHandle,SQL_HANDLE_STMT,hStmt.elseinvokeShowWindow,hList,SW_HIDEinvokeMessageBox,hDlg,addrAllocStmtFail,addrAppName,MB_OK+MB_ICONERROR.endifretRunQueryendpQueryProcprochDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD.ifuMsg==WM_CLOSEinvokeSQLFreeHandle,SQL_HANDLE_STMT,hStmtinvokeEndDialog,hDlg,0.elseifuMsg==WM_INITDIALOGinvokeShowWindow,hList,SW_SHOWinvokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokelstrcpy,addrConn,addrSQLStatementinvokelstrcat,addrConn,addrWhereStatementinvokeSQLBindParameter,hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,25,0,addrSearchName,25,addrStrLeninvokeSQLPrepare,hStmt,addrConn,sizeofConn.elseinvokeShowWindow,hList,SW_HIDEinvokeMessageBox,hDlg,addrAllocStmtFail,addrAppName,MB_OK+MB_ICONERRORinvokeEndDialog,hDlg,0.endif.elseifuMsg==WM_COMMANDmoveax,wParamshreax,16.ifax==BN_CLICKEDmoveax,wParam.ifax==IDC_OKinvokeGetDlgItemText,hDlg,IDC_NAME,addrSearchName,25.ifax==0invokeMessageBox,hDlg,addrNoData,addrAppName,MB_OK+MB_ICONERRORinvokeGetDlgItem,hDlg,IDC_NAMEinvokeSetFocus,eax.elseinvokelstrlen,addrSearchNamemovStrLen,eaxinvokeSendMessage,hList,LVM_DELETEALLITEMS,0,0invokeSQLExecute,hStmtinvokeFillDatainvokeSQLCloseCursor,hStmt.endif.elseinvokeSQLFreeHandle,SQL_HANDLE_STMT,hStmtinvokeEndDialog,hDlg,0.endif.endif.elsemoveax,FALSEret.endifmoveax,TRUEretQueryProcendpendstart
剖析
start:invokeGetModuleHandle,NULLmovhInstance,eaxcallGetProgramPath
当程序入手下手时,将取得实例句柄并取得地点路径.默许情形下数据库test.mdb应与程序处于统一文件夹.
GetProgramPathprocinvokeGetModuleFileName,NULL,addrProgPath,sizeofProgPathstdmovedi,offsetProgPathaddedi,sizeofProgPath-1moval,""movecx,sizeofProgPathrepnescasbcldmovbyteptr[edi+2],0retGetProgramPathendp
GetProgramPath挪用GetModuleFileName来取得程序的全路径名.接着在路径中查找最初一个""符",经由过程将文件名的第一个字符置为0取得(truncate)"文件名.因而我们在ProgPath中取得了程序的路径名.
然后程序将用DialogBoxParam显现主对话框.当主对话框第一次被载进时,它将取得菜单句柄和listviewcontrol句柄.接上去在listviewcontrol中拔出三列(由于我们已晓得了局集将包括三列.由于是我们先建的表.)
如今,它就守候用户的举措了.假如用户在菜单当选择"connect",将会挪用ODBCConnect函数.
ODBCConnectprochDlg:DWORDinvokeSQLAllocHandle,SQL_HANDLE_ENV,SQL_NULL_HANDLE,addrhEnv.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
它做的第一件事是挪用SQLAllocHandle来分派一个情况句柄.
invokeSQLSetEnvAttr,hEnv,SQL_ATTR_ODBC_VERSION,SQL_OV_ODBC3,0.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
取得情况句柄后,程序挪用SQLSetEnvAttr来暗示将要利用ODBC3.x的语法.
invokeSQLAllocHandle,SQL_HANDLE_DBC,hEnv,addrhConn.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
假如统统顺遂,程序将经由过程挪用SQLAllocHandle取得毗连句柄来完成毗连.
invokelstrcpy,addrConnectString,addrstrConnectinvokelstrcat,addrConnectString,addrProgPathinvokelstrcat,addrConnectString,addrDBName
接着填写毗连字符串.完全的毗连字符串将被用在ConnectionString
invokeSQLDriverConnect,hConn,hDlg,addrConnectString,sizeofConnectString,addrConn,sizeofConn,addrStrLen,SQL_DRIVER_COMPLETE.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokeSwitchMenuState,TRUEinvokeMessageBox,hDlg,addrConn,addrConnectCaption,MB_OK+MB_ICONINFORMATION
当毗连字符串完成,程序将挪用SQLDriverConnect来经由过程MSAccessODBC驱动程序毗连test.mdb数据库.假如文件test.mdb不存在,ODBCdriver将提醒用户输出该文件的地位,由于我们已设定了SQL_DRIVER_COMPLETE标记.当SQLDriverConnect乐成前往时,Conn被填进由ODBC驱动程序创立的完全毗连字符串.我们经由过程一个messagebox来将其显现给用户.SwitchMenuState是一个纯真切换菜单选项可用的函数.
如今,到数据库的毗连已创建并被翻开,并一向坚持翻开形态直到用户选择封闭.
当用户选择了"ViewAllRecords"命令,对话框历程将挪用RunQuery.函数
RunQueryprochDlg:DWORDinvokeShowWindow,hList,SW_SHOWinvokeSendMessage,hList,LVM_DELETEALLITEMS,0,0
因为listviewcontrol在创立时是不成见的,如今我们把它显现出来.另有要把个中的一切元素(假如有的话)删失落.
invokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
接上去,程序将取得一个语句句柄.
invokeSQLExecDirect,hStmt,addrSQLStatement,sizeofSQLStatement.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
经由过程SQLExecDirect实行已筹办好的SQL语句.我这里选择SQLExecDirect的缘故原由是只须实行一次.
invokeFillData
实行SQL语句后,将前往一个了局集.我们利用FillData函数来从了局会合解出数据并将其放进listviewcontrol中.
FillDataprocLOCALlvi:LV_ITEMLOCALrow:DWORDinvokeSQLBindCol,hStmt,1,SQL_C_CHAR,addrTheName,sizeofTheName,addrNameLengthinvokeSQLBindCol,hStmt,2,SQL_C_CHAR,addrTheSurname,sizeofTheSurname,addrSurnameLengthinvokeSQLBindCol,hStmt,3,SQL_C_CHAR,addrTelNo,sizeofTelNo,addrTelNoLength
如今,了局集被前往.我们要绑定了局集的一切三列到我们供应的缓冲区中.这是挪用SQLBindCol来完成的.注重我们要对每列分离挪用.而且我们其实不必要绑定一切的列:只需绑定要取得数据的列就好了.
movrow,0.whileTRUEmovbyteptrds:[TheName],0movbyteptrds:[TheSurname],0movbyteptrds:[TelNo],0
当列中没无数据时,我们初始化缓冲区为NULLs.更好的办法是用SQLBindCol指定的变量中数据的长度.在我们的例子中,我们能够反省NameLength,SurnameLength和TelNoLength中的值切实其实切长度.
invokeSQLFetch,hStmt.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOmovlvi.imask,LVIF_TEXT+LVIF_PARAMpushrowpoplvi.iItemmovlvi.iSubItem,0movlvi.pszText,offsetTheNamepushrowpoplvi.lParaminvokeSendMessage,hList,LVM_INSERTITEM,0,addrlvi
别的都很复杂了.挪用SQLFetch来取得了局集的一行,并将其存进listviewcontrol的缓冲区中.当没有更多的行供检索时(已抵达文件尾),SQLFetch前往SQL_NO_DATA而且程序跳出轮回.
invokeSQLCloseCursor,hStmtinvokeSQLFreeHandle,SQL_HANDLE_STMT,hStmt
当完成对了局集的操纵时,挪用SQLCloseCursor封闭了局集并挪用SQLFreeHandle开释语句句柄.
当用户选择"Query"命令,程序显现另外一个对话框供用户输出要查询的名字.
.elseifuMsg==WM_INITDIALOGinvokeShowWindow,hList,SW_SHOWinvokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFOinvokelstrcpy,addrConn,addrSQLStatementinvokelstrcat,addrConn,addrWhereStatementinvokeSQLBindParameter,hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,25,0,addrSearchName,25,addrStrLeninvokeSQLPrepare,hStmt,addrConn,sizeofConn
对话框做的第一件事是显现listviewcontrol.接上去分派一个语句句柄以创立SQL语句.这个SQL语句有一个"where"子句及一个参数标记符"?".完全的SQL语句是:
select*frommainwherename=?
接着程序挪用SQLBindParameter来创建参数标记符与缓冲区SearchName的毗连,如许当SQL语句被实行时,ODBC驱动程序便可从SearchName中取得必要的字符串.接上去,程序挪用SQLPrepare来编译SQL语句.如许我们只需筹办/编译SQL语句一次便可屡次利用.由于SQL语句已被编译过,接上去的实行历程会快一些.
.ifax==IDC_OKinvokeGetDlgItemText,hDlg,IDC_NAME,addrSearchName,25.ifax==0invokeMessageBox,hDlg,addrNoData,addrAppName,MB_OK+MB_ICONERRORinvokeGetDlgItem,hDlg,IDC_NAMEinvokeSetFocus,eax.else
当用户在编纂框(editcontrol)中填进了一些名字并按下回车键,程序将取得编纂框中的文本并反省是不是是空字符串.假如是,则显现一个messagebox并将键盘核心设在编纂框上,提醒用户输出名字.
invokelstrlen,addrSearchNamemovStrLen,eaxinvokeSendMessage,hList,LVM_DELETEALLITEMS,0,0invokeSQLExecute,hStmtinvokeFillDatainvokeSQLCloseCursor,hStmt
假如编纂框中已有字符串,程序会取得它的长度并将其放进StrLen中供ODBC驱动程序利用(记着我们已将StrLen的地点传送给了SQLBindParameter).接上去程序利用取得的语句句柄挪用SQLExecute实行已筹办好的SQL语句.当SQLExecute前往时,程序挪用FillData在listviewcontrol显现了局.由于我们不会再用到了局集,挪用SQLCloseCursor来封闭它.
导致了一个使用几乎和mSQL一样的API接口的用于他们的数据库的新的SQL接口的产生,这样,这个API被设计成允许为用于mSQL而写的第三方代码更容易移植到MySQL。 |
|