精华内容
下载资源
问答
  • sqlite3_exec
    2022-04-11 14:35:39
    int sqlite3_exec(
       sqlite3* ppDb,                             /* An open database */
       const char *sql,                           /* SQL to be evaluated */
       int (*callback)(void*,int,char**,char**),  /* Callback function */
       void *,                                    /* 1st argument to callback */
       char **errmsg                              /* Error msg written here */
    );//函数原型

    1、操作成功

    SQLITE_OK = 0; 返回成功

    2、操作失败

    SQLITE_ERROR = 1;         SQL错误或错误的数据库

    SQLITE_INTERNAL = 2;         An internal logic error in SQLite

    SQLITE_PERM = 3;         拒绝访问

    SQLITE_ABORT = 4;         回调函数请求中断

    SQLITE_BUSY = 5;         数据库文件被锁

    SQLITE_LOCKED = 6;         数据库中的一个表被锁

    SQLITE_NOMEM = 7;         内存分配失败

    SQLITE_READONLY = 8;         试图对一个只读数据库进行写操作

    SQLITE_INTERRUPT = 9;         由sqlite_interrupt()结束操作

    SQLITE_IOERR = 10;         磁盘I/O发生错误

    SQLITE_CORRUPT = 11;         数据库磁盘镜像畸形

    SQLITE_NOTFOUND = 12;         (Internal Only)表或记录不存在

    SQLITE_FULL = 13;         数据库满插入失败

    SQLITE_CANTOPEN = 14;         不能打开数据库文件

    SQLITE_PROTOCOL = 15;         数据库锁定协议错误

    SQLITE_EMPTY = 16;         (Internal Only)数据库表为空

    SQLITE_SCHEMA = 17;         数据库模式改变

    SQLITE_TOOBIG = 18;         对一个表数据行过多

    SQLITE_CONSTRAINT = 19;         由于约束冲突而中止(unique)

    SQLITE_MISMATCH = 20;         数据类型不匹配

    SQLITE_MISUSE = 21;         数据库错误使用

    SQLITE_NOLFS = 22;         使用主机操作系统不支持的特性

    SQLITE_AUTH = 23;         非法授权

    SQLITE_FORMAT = 24;         辅助数据库格式错误

    SQLITE_RANGE = 25;         2nd parameter to sqlite_bind out of range

    SQLITE_NOTADB = 26;         打开的不是一个数据库文件

    SQLITE_ROW = 100;         sqlite_step() has another row ready

    SQLITE_DONE = 101;         sqlite_step() has finished executing

    更多相关内容
  • 最近做到的项目涉及一个大数据量缓存重传,其中要用到的sqlite技术,把自己的学习心得整理了一下。 SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。同时能够跟很多程序...

    最近做到的项目涉及一个大数据量缓存重传,其中要用到的sqlite技术,把自己的学习心得整理了一下。

    SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite数据库由于其简单、灵活、轻量、开源,已经被越来越多的被应用到中小型应用中。因此在许多软件中例如(QQ,微信)等许多软件中都有广泛应用。
    在这里插入图片描述
    在这里插入图片描述

    sqlite应用蛮广泛的,小到app应用,大到服务器缓存。不同的插入方法有不同的优劣,在实际开发过程中,不要一味的追求快,而忽视了安全性。下面我就介绍几种我在这段学习过程中所了解的插入方式。

    慢插入-暴力插入

    在这里插入图片描述

    调用sqlite3_exec()函数,会隐式地开启了一个事务,其次,sqlite3_exec() 是sqlite3_perpare(),sqlite3_step(), sqlite3_finalize()的一个结合,每调用一次这个函数,就会重复的执行这三条语句,对于相同的语句,其中sqlite3_perpare相当于编译sql语句,如果语句相同且重复操作,就会增加很多重复操作。如果插入一条数据,就调该函数一次,事务就会被反复地开启、关闭,会增大IO量。所以当大批量数据插入时,此方法简直无法忍受。

    事务插入-显示的开启事务
    在这里插入图片描述
    在这里插入图片描述

    所谓”事务“就是指一组SQL命令,这些命令要么一起执行,要么都不被执行。如果在插入数据前显式开启事务,插入后再一起提交,

    则会大大提高IO效率,进而加数据快插入速度

    同步关闭模式-synchronous = OFF

    在这里插入图片描述

    当synchronous设置为FULL, SQLite数据库引擎在紧急时刻会暂停以确定数据已经写入磁盘。这使系统崩溃或电源出问题时能确保数据库在重起后不会损坏。FULL synchronous很安全但很慢。

    当synchronous设置为NORMAL, SQLite数据库引擎在大部分紧急时刻会暂停,但不像FULL模式下那么频繁。 NORMAL模式下有很小的几率(但不是不存在)发生电源故障导致数据库损坏的情况。但实际上,在这种情况 下很可能你的硬盘已经不能使用,或者发生了其他的不可恢复的硬件错误。

    当设置为synchronous OFF时,SQLite在传递数据给系统以后直接继续而不暂停。若运行SQLite的应用程序崩溃, 数据不会损伤,但在系统崩溃或写入数据时意外断电的情况下数据库可能会损坏。另一方面,在synchronous OFF时 一些操作可能会快50倍甚至更多。在SQLite 2中,缺省值为NORMAL.而在3中修改为FULL。

    执行前准备-sqlite3_prepare_v2

    在这里插入图片描述

    此方法就是“执行准备”(类似于存储过程)操作,即先将SQL语句编译好,然后再一步一步(或一行一行)地执行。如果采用前者的话,就算开起了事务,SQLite仍然要对循环中每一句SQL语句进行“词法分析”和“语法分析”,这对于同时插入大量数据的操作来说,简直就是浪费时间。因此,要进一步提高插入效率的话,就应该使用此方法

    测试结果展示
    在这里插入图片描述

    extern "C"
    {
        #include "sqlite3.h"
    };
    
    #include<sstream>
    #include <string>
    #include <iostream>
    #include <stdlib.h>
    #include <ctime>
    #include<windows.h>
    
    
    #define MAX_TEST_COUNT 200
    
    using namespace std;
    
    
    int main()
    {
        char cmdCreatTable[256] = "create table SqliteTest (id integer , x integer , y integer, weight real)" ;
        sqlite3* db = NULL;
        char * errorMessage = NULL;
        int iResult = sqlite3_open("SqliteTest.db", &db);
        do
        {
            if (SQLITE_OK != iResult)
            {
                cout<<"创建InsertTest.db文件失败"<<endl;
                break;
            }
    
            sqlite3_exec(db,"drop table if exists SqliteTest",0,0,0);
    
            iResult = sqlite3_exec(db, cmdCreatTable, NULL, NULL, &errorMessage);
            if (SQLITE_OK != iResult)
            {
                cout<<"创建表SqliteTest失败"<<endl;
                break;
            }
            DWORD timeStart;
            DWORD timeStop;
            timeStart = GetTickCount();
            for (int i = 0; i< MAX_TEST_COUNT; ++i)
            {
                stringstream ssm;
                ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
                iResult = sqlite3_exec(db,ssm.str().c_str(),0,0,0);
            }
            timeStop = GetTickCount();
            cout<< "直接Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间" << timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
    
            timeStart = GetTickCount();
            sqlite3_exec(db,"PRAGMA synchronous = OFF; ",0,0,0);
            for(int i = MAX_TEST_COUNT; i < MAX_TEST_COUNT*2; ++i)
            {
                stringstream ssm;
                ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
                sqlite3_exec(db,ssm.str().c_str(),0,0,0);
            }
            timeStop = GetTickCount();
    
            cout<< "同步写关闭+直接Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间" << timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
    
    
            timeStart = GetTickCount();
            sqlite3_exec(db,"PRAGMA synchronous = FULL; ",0,0,0);
            sqlite3_exec(db,"begin;",0,0,0);
            for(int i= MAX_TEST_COUNT*2; i< MAX_TEST_COUNT*3; ++i)
            {
                stringstream ssm;
                ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
                sqlite3_exec(db,ssm.str().c_str(),0,0,0);
            }
            sqlite3_exec(db,"commit;",0,0,0);
            timeStop = GetTickCount();
            cout<< "事务Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间"<< timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
    
    
            timeStart = GetTickCount();
            sqlite3_exec(db,"PRAGMA synchronous = OFF; ",0,0,0);
            sqlite3_exec(db,"begin;",0,0,0);
            for(int i = MAX_TEST_COUNT*3; i < MAX_TEST_COUNT*4; ++i)
            {
                stringstream ssm;
                ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
                sqlite3_exec(db,ssm.str().c_str(),0,0,0);
            }
            sqlite3_exec(db,"commit;",0,0,0);
            timeStop = GetTickCount();
    
            cout<< "事务+同步写关闭Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间" << timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
    
            timeStart = GetTickCount();
            //sqlite3_exec(db,"PRAGMA synchronous = FULL; ",0,0,0);
            sqlite3_exec(db,"begin;",0,0,0);
            sqlite3_stmt *stmt;
            const char* sql = "insert into SqliteTest values(?,?,?,?)";
            sqlite3_prepare(db,sql,strlen(sql),&stmt,0);
            for(int i = MAX_TEST_COUNT*4; i<MAX_TEST_COUNT*5; ++i)
            {
                sqlite3_reset(stmt);
                sqlite3_bind_int(stmt,1,i);
                sqlite3_bind_int(stmt,2,i*2);
                sqlite3_bind_int(stmt,3,i/2);
                sqlite3_bind_double(stmt,4,i*i);
                sqlite3_step(stmt);
             }
             sqlite3_finalize(stmt);
             sqlite3_exec(db,"commit;",0,0,0);
    
             timeStop = GetTickCount();
             cout<< "事务+执行准备+同步写关闭Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间:"<< timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
    
    
        }while(0);
    
        cout<<"插入测试结束"<<endl;
        Sleep(2000);
        sqlite3_close(db);
        system("pause");
    
    }
    
    展开全文
  • PC微信逆向--调用sqlite3_exec执行SQL

    千次阅读 2022-04-22 20:57:11
    文章目录写在前面回顾sqlite3_exec回调函数函数指针编写代码注入的DLL注入程序输出结果写在后面 写在前面 上一篇文章,实现了定位保存微信数据库句柄的容器和微信内部的sqlite3_exec函数地址,这一篇文章,尝试使用...

    写在前面

    上一篇文章,实现了定位保存微信数据库句柄的容器和微信内部的sqlite3_exec函数地址,这一篇文章,尝试使用得到的数据库句柄和sqlite3_exec,来查询数据库中的内容。

    回顾

    首先回顾一下上篇文章:PC微信逆向–定位sqlite3_exec和数据库句柄得到的结果,IDA中sqlite3_exec的地址是0x11356570,对应的偏移是0x11356570 - 0x10000000 = 0x1356570,对应微信中的地址:WeChatWin.dll + 0x1356570
    保存数据库句柄的容器首地址:[[WeChatWin.dll + 0x222F3FC] + 0x1888]
    保存数据库句柄的容器尾地址:[[WeChatWin.dll + 0x222F3FC] + 0x188C]

    sqlite3_exec

    int sqlite3_exec(
            sqlite3*,                                  /* An open database */
            const char *sql,                           /* SQL to be evaluated */
            int (*callback)(void*,int,char**,char**),  /* Callback function */
            void *,                                    /* 1st argument to callback */
            char **errmsg                              /* Error msg written here */
    );
     sqlite3*:通过sqlite3_open打开的数据库句柄 
     const char *sql:要执行的sql语句
     int (*callback)(void*,int,char**,char**):执行sql语句时对应的回调函数
     void *:回调函数的参数
     char **errmsg:存放错误信息
    

    上一篇文章只关注了参数个数,以及默认调用约定,这一次需要理解每个参数的作用,才能在调用的时候不出错。
    第一个参数是数据库句柄,已经拿到了。
    第二个参数是要执行的SQL语句,为了必定执行成功,以下面这句作为测试:

    select * from sqlite_master where type='table';
    

    第三个参数是回调函数,每查询出一条数据,都会调用一次回调函数,毫无疑问,这个参数是最重要的,等下单独讲解。
    第四个参数是传递给回调函数的参数,这是一个void*参数,必须在回调函数里面解引用,如果不需要,可以写0。
    第五个参数是错误信息,这个对我们来说不重要,可以写0。
    最后还要说一下返回值,如果SQL执行成功,sqlite3_exec返回0,如果失败,返回非0值。

    回调函数

    来看一个官方的例子:

    static int callback(void *NotUsed, int argc, char **argv, char **azColName){
        int i;
        for(i=0; i<argc; i++){
          printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
        }
        printf("\n");
        return 0;
      }
    

    第一个参数是为sqlite3_exec设置的第四个参数。
    第二个参数是本次查询得到的字段个数。
    第三个参数是char**,可以将其理解为保存char*的容器,所有成员都是char*类型,实际上保存的是字段的值。
    第四个参数和第三个参数类似,并且成员一一对应,保存的是字段名。

    函数指针

    这个就很简单了,用typedef声明一个函数指针,并且解引用微信中的sqlite3_exec,就在不引入sqlite3库的情况下得到了sqlite3_exec函数:

    typedef int(__cdecl* Sqlite3_exec)(
      DWORD,                    /* The database on which the SQL executes */
      const char *,             /* The SQL to be executed */
      sqlite3_callback,         /* Invoke this callback routine */
      void *,                   /* First argument to xCallback() */
      char **                   /* Write error messages here */
    );
    

    这段代码是我抄来的,可能有人会问,第一个参数,应该是sqlite3*类型,这里改成DOWRD,会不会有问题。在32位汇编中,指针(不管是void*还是其他什么*或者**)和DWORD都占用4个字节,对于目标函数来说,都是地址而已,只要结构正确,就不会有问题。(如果理解有误望大佬指正)。
    此外,还需要sqlite3_callback函数指针:

    typedef int(*sqlite3_callback)(
    	void*,
    	int,
    	char**,
    	char**
    );
    

    编写代码

    终于到了万众瞩目的写代码环节,要实现两个功能,一个是DLL,进入微信内部干活,另外一个是注入程序,帮助DLL进入微信内部干活。

    注入的DLL

    相信这些代码你一看就能懂:
    sqlite_exec.h

    #pragma once
    #include<windows.h>
    #include<iostream>
    #include<vector>
    using namespace std;
    void __stdcall execute();
    

    sqlite_exec.cpp

    #include "pch.h"
    #include "sqlite_exec.h"
    
    #define sqlite3_exec_offset 0x1356570
    #define db_handles_base_offset 0x222F3FC
    
    // 回调函数指针
    typedef int(*sqlite3_callback)(
    	void*,
    	int,
    	char**,
    	char**
    );
    
    // sqlite3_exec函数指针
    typedef int(__cdecl* Sqlite3_exec)(
    	DWORD,                    /* The database on which the SQL executes */
    	const char*,              /* The SQL to be executed */
    	sqlite3_callback,         /* Invoke this callback routine */
    	void*,                    /* First argument to xCallback() */
    	char**                    /* Write error messages here */
    );
    
    // 保存数据库句柄和数据库名的结构体
    struct dbStruct {
    	DWORD dbhandle;
    	wchar_t* dbname;
    };
    
    // 保存数据库信息的容器
    vector<dbStruct> dbhandles;
    
    // 创建一个Console窗口,方便观察输出结果
    BOOL CreateConsole(void) {
    	if (AllocConsole()) {
    		AttachConsole(GetCurrentProcessId());
    		FILE* retStream;
    		freopen_s(&retStream, "CONOUT$", "w", stdout);
    		if (!retStream) throw std::runtime_error("Stdout redirection failed.");
    		freopen_s(&retStream, "CONOUT$", "w", stderr);
    		if (!retStream) throw std::runtime_error("Stderr redirection failed.");
    		return 0;
    	}
    	return 1;
    }
    
    // 获取WeChatWin.dll的基址
    DWORD GetWeChatWinBase() {
    	DWORD WeChatWinBase = (DWORD)GetModuleHandle(L"WeChatWin.dll");
    	return WeChatWinBase;
    }
    
    // 获取数据库句柄和数据库名并存入容器
    void GetHandles() {
    	DWORD WeChatWinBase = GetWeChatWinBase();
    	DWORD SqlHandleBaseAddr = *(DWORD*)(WeChatWinBase + db_handles_base_offset);
    	DWORD SqlHandleBeginAddr = *(DWORD*)(SqlHandleBaseAddr + 0x1888);
    	DWORD SqlHandleEndAddr = *(DWORD*)(SqlHandleBaseAddr + 0x188C);
    	wstring dbnames = L"";
    	while (SqlHandleBeginAddr < SqlHandleEndAddr) {
    		DWORD dwHandle = *(DWORD*)SqlHandleBeginAddr;
    		SqlHandleBeginAddr += 0x4;
    		// 做一下简单的去重
    		if (dbnames.find((wchar_t*)(*(DWORD*)(dwHandle + 0x78)), 0) != wstring::npos)
    			continue;
    		dbStruct db = { 0 };
    		db.dbname = (wchar_t*)(*(DWORD*)(dwHandle + 0x78));
    		dbnames += (wchar_t*)(*(DWORD*)(dwHandle + 0x78));
    		db.dbhandle = *(DWORD*)(dwHandle + 0x64);
    		dbhandles.push_back(db);
    	}
    }
    
    // 回调函数的实现,官方例子未做改动
    static int callback(void* NotUsed, int argc, char** argv, char** azColName) {
    	int i;
    	for (i = 0; i < argc; i++) {
    		printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    	}
    	printf("\n");
    	return 0;
    }
    
    // 由dllmain调用的入口函数
    void __stdcall execute() {
    	CreateConsole();
    	const char* sql = "select * from sqlite_master where type=\"table\";";
    	DWORD WeChatWinBase = GetWeChatWinBase();
    	Sqlite3_exec p_Sqlite3_exec = (Sqlite3_exec)(WeChatWinBase + sqlite3_exec_offset);
    	GetHandles();
    	for (unsigned int i = 0; i < dbhandles.size(); i++) {
    		printf("dbname: %ws\n", dbhandles[i].dbname);
    		p_Sqlite3_exec(dbhandles[i].dbhandle, sql, (sqlite3_callback)callback, 0, 0);
    	}
    }
    

    dllmain.cpp

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "pch.h"
    #include "sqlite_exec.h"
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        {
            // 程序注入后,会执行到此处
            execute();
        }
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    

    注入程序

    本来想发个工具,但还要弄网盘啥的,还是抄一点代码吧,轻松加愉快。

    #include <iostream>
    #include <windows.h>
    using namespace std;
    
    // 注入DLL到微信的进程空间
    bool InjectDll(DWORD dwId, WCHAR* szPath)//参数1:目标进程PID  参数2:DLL路径
    {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
        /*
        【1.2 在目标进程的内存里开辟空间】
        */
        LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
    
        //二、 把dll的路径写入到目标进程的内存空间中
        DWORD dwWriteSize = 0;
        /*
        【写一段数据到刚才给指定进程所开辟的内存空间里】
        */
        if (pRemoteAddress)
        {
            WriteProcessMemory(hProcess, pRemoteAddress, szPath, wcslen(szPath) * 2 + 2, &dwWriteSize);
        }
        else {
            printf("写入失败!\n");
            return 1;
        }
    
        //三、 创建一个远程线程,让目标进程调用LoadLibrary
        HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pRemoteAddress, NULL, NULL);
        if (hThread) {
            WaitForSingleObject(hThread, -1);
        }
        else {
            printf("调用失败!\n");
            return 1;
        }
        CloseHandle(hThread);
        VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return 0;
    }
    
    // 目标进程卸载DLL,释放Console窗口
    BOOL RemoveDll(DWORD dwId,wchar_t* dllname) {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
        LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
        DWORD dwWriteSize = 0;
        HANDLE hThread = NULL;
        DWORD dwHandle, dwID;
        LPVOID pFunc = NULL;
        if (pRemoteAddress)
            WriteProcessMemory(hProcess, pRemoteAddress, dllname, wcslen(dllname) * 2 + 2, &dwWriteSize);
        else {
            printf("写入失败!\n");
            return 1;
        }
        hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetModuleHandleW, pRemoteAddress, 0, &dwID);
        if (hThread) {
            WaitForSingleObject(hThread, INFINITE);
            GetExitCodeThread(hThread, &dwHandle);
        }
        else {
            printf("GetModuleHandleW调用失败!\n");
            return 1;
        }
        CloseHandle(hThread);
    
        // 释放console窗口,不然关闭console的同时微信也会退出
        hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)FreeConsole, NULL, 0, &dwID);
        if (hThread) {
            WaitForSingleObject(hThread, INFINITE);
        }
        else {
            printf("FreeConsole调用失败!\n");
            return 1;
        }
        CloseHandle(hThread);
    
        // 使目标进程调用FreeLibrary,卸载DLL
        hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, (LPVOID)dwHandle, 0, &dwID);
        if (hThread) {
            WaitForSingleObject(hThread, INFINITE);
        }
        else {
            printf("FreeLibrary调用失败!\n");
            return 1;
        }
        CloseHandle(hThread);
        VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return 0;
    }
    
    // 获取当前工作目录,拼接DLL绝对路径
    wchar_t* GetDllPath(wchar_t* dllname) {
        wchar_t* dllpath = new wchar_t[MAX_PATH];
        wchar_t workPath[MAX_PATH];
        wchar_t* pworkPath = _wgetcwd(workPath, MAX_PATH);
        swprintf_s(dllpath, MAX_PATH, L"%ws%ws%ws", pworkPath, L"\\", dllname);
        return dllpath;
    }
    
    // 主函数
    int main(int nargv, WCHAR* argvs[])
    {
        HWND hCalc = FindWindow(NULL, L"微信");
        DWORD dwPid = 0;
        DWORD dwRub = GetWindowThreadProcessId(hCalc, &dwPid);
        if (!dwPid) {
            printf("%s\n","请先启动目标进程!");
            return 1;
        }
        wchar_t* dllname = (wchar_t*)L"DbTest.dll";
        wchar_t* dllpath = GetDllPath(dllname);
        InjectDll(dwPid, dllpath);
        delete[] dllpath;
        dllpath = NULL;
        system("pause");
        RemoveDll(dwPid, dllname);
        return 0;
    }
    

    平台配置为win32(x86),笔者编译环境为VS 2019社区版。

    输出结果

    写在后面

    本篇文章使用上一篇文章:PC微信逆向–定位sqlite3_exec和数据库句柄找到的sqlite3_exec函数地址和数据库句柄,成功绕过加密执行了SQL,下一篇文章,介绍如何寻找微信内部的sqlite3 API,为在线备份做铺垫。

    展开全文
  • sqlite3_exec()函数归纳

    千次阅读 2020-08-26 14:44:52
    一、sqlite3_exec函数介绍 sqlite3_execsqlite3的接口API函数 源码API接口截图 1.参数分析: int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callba

    一、sqlite3_exec函数介绍
    sqlite3_exec是sqlite3的接口API函数
    源码API接口截图
    在这里插入图片描述
    1.参数分析:

    int sqlite3_exec(
            sqlite3*,                                  /* An open database */
            const char *sql,                           /* SQL to be evaluated */
            int (*callback)(void*,int,char**,char**),  /* Callback function */
            void *,                                    /* 1st argument to callback */
            char **errmsg                              /* Error msg written here */
    );
     sqlite3*:打开的数据库			    const char *sql:要执行的sql语句
     int (*callback)(void*,int,char**,char**):执行sql语句时对应的回调函数
     void *:回调函数的参数				char **errmsg:存放错误信息
    

    2.回调函数分析:int (*callback)(void*,int,char**,char**); || int callback(void *arg, int column_size, char *column_value[], char *column_name[])

    参数分析:void *arg:是sqlite3_exec函数的第四个参数		column_size:数据库的字段数
    		column_value[]:列的值 						column_name:字段名字
    

    源码解释:
    在这里插入图片描述
    3.使用demon

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sqlite3.h>
    
    int callback(void *arg, int column_size, char *column_value[], char *column_name[]){
    	static int count = 0;
    	int i;
    	printf("%s\n", (char *)arg);
    	if(0 == count){
    		for(i = 0; i < column_size; i++){
    			printf("%-8s\t", column_name[i]);
    		}
    		printf("\n");
    	}
    	for(i = 0; i < column_size; i++){
    		printf("%-8s\t", column_value[i]);
    	}
    	printf("\n");
    	printf("size is %d \n",column_size);
    	count++;
    	printf("%d\n",count);
    	return 0;
    }
    
    
    int main(int argc, const char **argv)
    {
    	sqlite3 *db = NULL;
    	int ret;
    	char sql[1024] = "\0";
    	char *errmsg = NULL;
    	if(argc < 5){
    		fprintf(stderr, "please input:%s name id score sex\n", argv[0]);
    		exit(EXIT_FAILURE);//异常退出
    	}
    	//step 1: 创建数据库
    	ret = sqlite3_open("./student.db", &db);//存在打开,不存在创建
    	if(SQLITE_OK != ret){
    		fprintf(stderr, "sqlite3_open:%s\n", sqlite3_errmsg(db));
    		exit(EXIT_FAILURE);//异常退出
    	}
    	//step 2: 建表
    	sprintf(sql, "create table if not exists student (name text, id integer, score real ,sex text)");
    	ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
    	if(SQLITE_OK != ret){
    		fprintf(stderr, "create table:%s\n", sqlite3_errmsg(db));
    		fprintf(stderr, "create table:%s\n", errmsg);
    		exit(EXIT_FAILURE);//异常退出
    	}
    	//step3: 插入数据
    	sprintf(sql, "insert into student (name, id, score, sex) values ('%s', '%s', '%s','%s')", argv[1], argv[2], argv[3], argv[4]);
    	ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
    	if(SQLITE_OK != ret){
    		fprintf(stderr, "insert into:%s\n", sqlite3_errmsg(db));
    		fprintf(stderr, "insert into:%s\n", errmsg);
    		exit(EXIT_FAILURE);//异常退出
    	}
    	//step4: 查询	
    	sprintf(sql, "select * from student ");
    	ret = sqlite3_exec(db, sql, callback, "callback msg", &errmsg);
    	if(SQLITE_OK != ret){
    		fprintf(stderr, "select:%s\n", sqlite3_errmsg(db));
    		fprintf(stderr, "select:%s\n", errmsg);
    		exit(EXIT_FAILURE);//异常退出
    	}
    
    	//last step :关闭数据库
    	sqlite3_close(db);
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述

    展开全文
  • 一)sqlite3_exec 1.头文件和函数原型 #include "sqlite3.h" int sqlite3_exec(sqlite3*, const char *sql, int (*callback)(void*para,int argc,char**argv,char**argv_name), void *para,char **errmsg) 2.说明 ...
  • sqlite3的C/C++接口API主要有3个重要函数,分别为 1、sqlite3_open(const char* filename, sqlite3 **ppDb)...2、int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */
  • Sqlite3 的确非常好用。小巧、速度快。近期研究它,有一些收获,这里把我对 sqlite3 的研究列出来,以备忘记。  导入SQLLite library并引入头文件.  libsqlite3.dylib本身是个链接,在这里它指向libsqlite3.0...
  • 关于sqlite3_exec的回调函数的知识,我也是在做一个项目中学习到的,看了一些博客吧,很多博客,都表达的不是很清楚,所以我想写这篇博客,记录自己的学习过程。大家先了解一下sqlite3_exec()函数吧。 1、sqlite3_...
  • 目标 需要分步实现下面的目标: 定位sqlite3_exec函数 获取微信打开的数据库句柄 调用微信内部的sqlite3_exec执行SQL 定位sqlite3_open、sqlite3_backup_init等函数 完成数据库在线备份 定位数据库密码的保存位置 ...
  • sqlite_step()在执行select时使用,因为查询到的结果可能会有多条,所以只要返回值是SQLITE_ROW,就要一直循环去获取...而sqlite3_exec()则是对insert、update,delete等执行后只影响数据库中的内容的操作时使用。 ...
  • sqlite3_exec的函数原型: int sqlite3_exec( sqlite3 *pDb, const char *sql, int (*callback)(void *arg, int col, char **str, char **name), void *arg, char **errmsg ) 参数说明: pDb:打开数据库的句柄 sql...
  • 打开数据库链接sqlite3_open用法 原型: int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); 用这个函数开始数据库操作。需要传入两个...
  • sqlite3_exec返回SQLITE_MISUSE(21)

    千次阅读 2020-07-10 18:00:09
    sqlite3版本3.29.0 sqlite3打开数据的路径中有中文时,sqlite3_exec会返回这个错误,将中文转utf8就好了
  • 数据库函数:sqlite3_exec() SQL语句

    千次阅读 2017-12-19 09:41:00
    函数:sqlite3_exec(),称为便捷函数,封装了好多任务。 函数声明: int sqlite3_exec( sqlite * , const char * sql , sqlite_callback , void *data , char ** errmmsg) ; 其中 sqlite* 表示打开的数据库; ...
  • 使用sqlite3_exec函数时,没有添加返回值,导致出现如上述错误: sqlite3_exec error :query aborted 继续测试发现,如果回调函数返回1,依然出现上述错误。 回调函数返回0,则不会出现。 总结: 应该是...
  • sqlite3_exec

    万次阅读 2014-12-11 14:01:54
    函数:sqlite3_exec(),称为便捷函数,封装了好多任务。  函数声明:  int sqlite3_exec( sqlite * , const char * sql , sqlite_callback , void *data , char ** errmmsg) ; 其中 sqlite* 表示打开的...
  • sqlite3函数sqlite3_exec

    千次阅读 2016-04-20 22:01:54
    函数:sqlite3_exec(),称为便捷函数,封装了好多任务。  函数声明:  int sqlite3_exec( sqlite * , const char * sql , sqlite_callback , void *data , char ** errmmsg) ; 其中 sqlite* 表示打开的...
  • 今天老大突然告诉我,他的手机升了... int result = sqlite3_exec(db, [sqlite UTF8String], nil, nil, &amp;error); 原因暂时不清楚,如果有清楚的麻烦告诉我一下,感谢! 解决方法: 替换为下面的方法:...
  • 数据库操作 ——sqlite3_exec

    千次阅读 2017-08-06 23:17:50
    #include #include int LoadMyInfo( void * para, int n_column, ...//para是你在 sqlite3_exec 里传入的 void * 参数 //通过para参数,你可以传入一些特殊的指针(比如类指针、结构指针),然后在这里面强
  • sqlite3_exec使用inner join的话查询返回结果是sqlite_ok的,但是拿不到结果,并且连回调函数都没有进入,起初以为是我sql语句写错了,但是在sqlitestudio中使用的话,是能查询到结果的,而且和预期一样,语句都是用...
  • 不知道有没有人跟我一样,在调用sqlite3的API中sqlite3_exec()函数时出现abort问题,今天我就遇到了,如下图。 函数基本原型为:  int sqlite3_exec(sqlite3*,const char *sql,sqlite_callback,void *param,...
  • 打开数据库链接sqlite3_open用法 原型: int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); 用这个函数开始数据库操作。需要...
  • 笔记
  • sqlite3_exec函数的使用

    千次阅读 2013-11-06 20:55:00
    int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback, void *,char **errmsg); 功能:执行sql语句 参数: db:数据库句柄 sql:sql语句 callback:回调函数,每成功执行一次sql语句...
  •  ret = sqlite3_exec(db,sql,my_callback,NULL,&errmsg); if(ret == SQLITE_OK) { printf("select error : %s\n",errmsg); } printf("input any character\n");  getchar(); }
  • 使用sqlite3_exec 插入100万行数据...主要是因为采用sqlite3_exec(),相当于每插入一行数据同时用到sqlite3_prepare_v2(), sqlite3_step() 和 sqlite3_finalize(),另外需要把double 强制转换成 string 然后再转换成
  • 报错:Apple Mach-O Linker Error "_sqlite3_exec", referenced from: "_sqlite_open", referenced from: "_sqlite3_prepare_v2", referenced from "_sqlite3_column_count" referenced From: 点击项目名称 ...
  • sql操作sqlite3_exec

    万次阅读 2014-05-07 11:13:55
    int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); 用这个函数开始数据库操作。需要传入两个参数,一是数据库文件名,比如:E:/test...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 38,103
精华内容 15,241
关键字:

sqlite3_exec