Статья ASM – работа с базами SQLite (часть 2. Читаем cookies браузеров)

Рассмотрев в предыдущей части формат и основные возможности подсистемы SQLite, перейдём к операциям с данными, которые осуществляются посредством вызова методов из библиотеки sqlite3.dll. Самая последняя версия 3.35.05 этой либы выдаёт на экспорт всего 329 функций, предоставляя нам широкий выбор действий. Некоторые из них могут иметь переменное число параметров, и автор не стал делать на них акцент. Он просто оформил все функции с соглашением о вызове "cdecl" (декларация языка С++), а не стандартным "stdcall". Это означает, что на выходе, ответственность за очистку аргументов функции в стеке полностью возложена на нас, для чего ассемблер FASM имеет макросы cinvoke и ccall (последний используется для вызовов по указателю). Экскурсии по часто используемым функциям и посвящена данная часть статьи.

Содержание:


1. Основные функции библиотеки sqlite3.dll;
• операторы и оформление запросов;
2. Практика – чтение структуры базы-данных ;
3. Практика – собираем "cookies" браузеров.

---------------------------------------

Одним из недостатков компилятора FASM (по сравнению с тем-же масмом) является отсутствие в базовом его пакете большинства заголовочных файлов с описанием структур. Томас Грыштар ограничился лишь основными библиотеками типа User/Shell/Kernel32.dll, зато предусмотрел простую возможность добавления сторонних инклуд, по мере их необходимости. В частности, это относится к перечислению импорта из статически подключаемых библиотек при компиляции проектов. Применительно к указанным выше DLL, освобождают нас от этой рутины файлы из папки FASM\INCLUDE\API, в которых перечислены все функции экспорта каждой из DLL. Теперь, просто подключив их к своему исходному коду, нам не нужно импортировать функции явно – компилятор сам позаботится об этом.

Чтобы добавить красок в работу с базами-данных SQLite, я (придерживаясь рекомендаций автора fasm) создал точно такой-же инклуд импорта, только для библиотеки sqlite3.dll. Результат настолько воодушевил, что не поленился собрать аналогичный инклуд сразу и для консольной либы msvcrt.dll – оба этих файла можно будет найти в скрепке, в подвале статьи. В итоге, служебная часть исходника остаётся за его периметром во-внешних инклудах, что повышает читабельность кода.

HDasm.png


Код:
File         :  sqlite3.dll
Version      :  3.35.5
Size         :  1071715 byte
Type         :  PE
Base Of Code :  00001000,  Code Size: 000ABC00
Base Of Data :  000AD000,  Data Size: 000CA400
Image Base   :  61E00000
Entry Point  :  61E01400

File sections:

   Name   | VirtAddr | VirtSize |  Offset  | PhysSize |  Flags   | Code
----------+----------+----------+----------+----------+----------+------
 .text    | 61E01000 | 000ABAF0 | 00000600 | 000ABC00 | 60500060 | Yes
 .data    | 61EAD000 | 000022DC | 000AC200 | 00002400 | C0600040 |
 .rdata   | 61EB0000 | 00013AB0 | 000AE600 | 00013C00 | 40600040 |
 .bss     | 61EC4000 | 00000828 | 00000000 | 00000000 | C0600080 |
 .edata   | 61EC5000 | 0000292B | 000C2200 | 00002A00 | 40300040 |
 .idata   | 61EC8000 | 00000CD0 | 000C4C00 | 00000E00 | C0300040 |
 .CRT     | 61EC9000 | 0000002C | 000C5A00 | 00000200 | C0300040 |
 .tls     | 61ECA000 | 00000020 | 000C5C00 | 00000200 | C0300040 |
 .rsrc    | 61ECB000 | 000004A8 | 000C5E00 | 00000600 | C0300040 |
 .reloc   | 61ECC000 | 00003A28 | 000C6400 | 00003C00 | 42300040 |
 /4       | 61ED0000 | 00000538 | 000CA000 | 00000600 | 42400040 |
 /19      | 61ED1000 | 0000C852 | 000CA600 | 0000CA00 | 42100040 |
 /31      | 61EDE000 | 0000275D | 000D7000 | 00002800 | 42100040 |
 /45      | 61EE1000 | 00002D9A | 000D9800 | 00002E00 | 42100040 |
 /57      | 61EE4000 | 00000B5C | 000DC600 | 00000C00 | 42300040 |
 /70      | 61EE5000 | 00000323 | 000DD200 | 00000400 | 42100040 |
 /81      | 61EE6000 | 00003A73 | 000DD600 | 00003C00 | 42100040 |
 /92      | 61EEA000 | 00000350 | 000E1200 | 00000400 | 42100040 |


Number of Exported Functions = 0329 (decimal)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 Addr:61E16307   Ord:   1 (0001h)    Name: sqlite3_aggregate_context
 Addr:61E034E5   Ord:   2 (0002h)    Name: sqlite3_aggregate_count
 Addr:61EA373D   Ord:   3 (0003h)    Name: sqlite3_auto_extension
 Addr:61E530BD   Ord:   4 (0004h)    Name: sqlite3_backup_finish
 Addr:61E52C23   Ord:   5 (0005h)    Name: sqlite3_backup_init
 Addr:61E03043   Ord:   6 (0006h)    Name: sqlite3_backup_pagecount
 Addr:61E03038   Ord:   7 (0007h)    Name: sqlite3_backup_remaining
 Addr:61E50B80   Ord:   8 (0008h)    Name: sqlite3_backup_step
 Addr:61E25476   Ord:   9 (0009h)    Name: sqlite3_bind_blob
 Addr:61E2549D   Ord:  10 (000Ah)    Name: sqlite3_bind_blob64
 Addr:61E25176   Ord:  11 (000Bh)    Name: sqlite3_bind_double
 Addr:61E25216   Ord:  12 (000Ch)    Name: sqlite3_bind_int
 Addr:61E251C7   Ord:  13 (000Dh)    Name: sqlite3_bind_int64
 Addr:61E2523C   Ord:  14 (000Eh)    Name: sqlite3_bind_null
 Addr:61E03523   Ord:  15 (000Fh)    Name: sqlite3_bind_parameter_count
 Addr:61E1A0B4   Ord:  16 (0010h)    Name: sqlite3_bind_parameter_index
 Addr:61E03535   Ord:  17 (0011h)    Name: sqlite3_bind_parameter_name
 Addr:61E2526D   Ord:  18 (0012h)    Name: sqlite3_bind_pointer
 Addr:61E254E4   Ord:  19 (0013h)    Name: sqlite3_bind_text
 Addr:61E25578   Ord:  20 (0014h)    Name: sqlite3_bind_text16
 Addr:61E2550B   Ord:  21 (0015h)    Name: sqlite3_bind_text64
 Addr:61E2559F   Ord:  22 (0016h)    Name: sqlite3_bind_value
 Addr:61E252EA   Ord:  23 (0017h)    Name: sqlite3_bind_zeroblob
 Addr:61E25357   Ord:  24 (0018h)    Name: sqlite3_bind_zeroblob64
 Addr:61E03605   Ord:  25 (0019h)    Name: sqlite3_blob_bytes
 Addr:61E543A9   Ord:  26 (001Ah)    Name: sqlite3_blob_close
 Addr:61E8F3FE   Ord:  27 (001Bh)    Name: sqlite3_blob_open
 Addr:61E56167   Ord:  28 (001Ch)    Name: sqlite3_blob_read
 Addr:61E8FB94   Ord:  29 (001Dh)    Name: sqlite3_blob_reopen
 Addr:61E56EC9   Ord:  30 (001Eh)    Name: sqlite3_blob_write
 Addr:61E056F9   Ord:  31 (001Fh)    Name: sqlite3_busy_handler
 Addr:61E0DE4E   Ord:  32 (0020h)    Name: sqlite3_busy_timeout
 Addr:61E041C5   Ord:  33 (0021h)    Name: sqlite3_cancel_auto_extension
 Addr:61E055BB   Ord:  34 (0022h)    Name: sqlite3_changes
 Addr:61E0AFAD   Ord:  35 (0023h)    Name: sqlite3_clear_bindings
 Addr:61E532B7   Ord:  36 (0024h)    Name: sqlite3_close
 Addr:61E532C5   Ord:  37 (0025h)    Name: sqlite3_close_v2
 Addr:61E05A02   Ord:  38 (0026h)    Name: sqlite3_collation_needed
 Addr:61E05A46   Ord:  39 (0027h)    Name: sqlite3_collation_needed16
 Addr:61E21569   Ord:  40 (0028h)    Name: sqlite3_column_blob
 Addr:61E212F9   Ord:  41 (0029h)    Name: sqlite3_column_bytes
 Addr:61E213CD   Ord:  42 (002Ah)    Name: sqlite3_column_bytes16
 Addr:61E034F3   Ord:  43 (002Bh)    Name: sqlite3_column_count
 Addr:61E224D3   Ord:  44 (002Ch)    Name: sqlite3_column_database_name
 Addr:61E224EB   Ord:  45 (002Dh)    Name: sqlite3_column_database_name16
 Addr:61E224A0   Ord:  46 (002Eh)    Name: sqlite3_column_decltype
 Addr:61E224B8   Ord:  47 (002Fh)    Name: sqlite3_column_decltype16
 Addr:61E2BC85   Ord:  48 (0030h)    Name: sqlite3_column_double
 Addr:61E11245   Ord:  49 (0031h)    Name: sqlite3_column_int
 Addr:61E11271   Ord:  50 (0032h)    Name: sqlite3_column_int64
 Addr:61E2246D   Ord:  51 (0033h)    Name: sqlite3_column_name
 Addr:61E22485   Ord:  52 (0034h)    Name: sqlite3_column_name16
 Addr:61E22539   Ord:  53 (0035h)    Name: sqlite3_column_origin_name
 Addr:61E22551   Ord:  54 (0036h)    Name: sqlite3_column_origin_name16
 Addr:61E22506   Ord:  55 (0037h)    Name: sqlite3_column_table_name
 Addr:61E2251E   Ord:  56 (0038h)    Name: sqlite3_column_table_name16
 Addr:61E216A2   Ord:  57 (0039h)    Name: sqlite3_column_text
 Addr:61E2256C   Ord:  58 (003Ah)    Name: sqlite3_column_text16
 Addr:61E11315   Ord:  59 (003Bh)    Name: sqlite3_column_type
 Addr:61E1129A   Ord:  60 (003Ch)    Name: sqlite3_column_value
 Addr:61E058B2   Ord:  61 (003Dh)    Name: sqlite3_commit_hook
 Addr:61E05B44   Ord:  62 (003Eh)    Name: sqlite3_compileoption_get
 Addr:61E09874   Ord:  63 (003Fh)    Name: sqlite3_compileoption_used
 Addr:61E05295   Ord:  64 (0040h)    Name: sqlite3_complete
 Addr:61EA38E3   Ord:  65 (0041h)    Name: sqlite3_complete16
 Addr:61E3240D   Ord:  66 (0042h)    Name: sqlite3_config
 Addr:61E03482   Ord:  67 (0043h)    Name: sqlite3_context_db_handle
 Addr:61E2B2C2   Ord:  68 (0044h)    Name: sqlite3_create_collation
 Addr:61E2B2F9   Ord:  69 (0045h)    Name: sqlite3_create_collation16
 Addr:61E2B26B   Ord:  70 (0046h)    Name: sqlite3_create_collation_v2
 Addr:61E373B4   Ord:  71 (0047h)    Name: sqlite3_create_filename
 Addr:61E2AC20   Ord:  72 (0048h)    Name: sqlite3_create_function
 Addr:61E2AFF2   Ord:  73 (0049h)    Name: sqlite3_create_function16
 Addr:61E2AE6A   Ord:  74 (004Ah)    Name: sqlite3_create_function_v2
 Addr:61E1C351   Ord:  75 (004Bh)    Name: sqlite3_create_module
 Addr:61E1C39B   Ord:  76 (004Ch)    Name: sqlite3_create_module_v2
 Addr:61E2AEB0   Ord:  77 (004Dh)    Name: sqlite3_create_window_function
 Addr:61E03508   Ord:  78 (004Eh)    Name: sqlite3_data_count
 Addr:61EC4020   Ord:  79 (004Fh)    Name: sqlite3_data_directory
 Addr:61E02823   Ord:  80 (0050h)    Name: sqlite3_database_file_object
 Addr:61E505BC   Ord:  81 (0051h)    Name: sqlite3_db_cacheflush
 Addr:61E13FC8   Ord:  82 (0052h)    Name: sqlite3_db_config
 Addr:61E130E6   Ord:  83 (0053h)    Name: sqlite3_db_filename
 Addr:61E03552   Ord:  84 (0054h)    Name: sqlite3_db_handle
 Addr:61E05534   Ord:  85 (0055h)    Name: sqlite3_db_mutex
 Addr:61E05B22   Ord:  86 (0056h)    Name: sqlite3_db_readonly
 Addr:61E19CBF   Ord:  87 (0057h)    Name: sqlite3_db_release_memory
 Addr:61E1C423   Ord:  88 (0058h)    Name: sqlite3_db_status
 Addr:61E83B89   Ord:  89 (0059h)    Name: sqlite3_declare_vtab
 Addr:61E8626F   Ord:  90 (005Ah)    Name: sqlite3_deserialize
 Addr:61E1C3B9   Ord:  91 (005Bh)    Name: sqlite3_drop_modules
 Addr:61E323C7   Ord:  92 (005Ch)    Name: sqlite3_enable_load_extension
 Addr:61E02ABE   Ord:  93 (005Dh)    Name: sqlite3_enable_shared_cache
 Addr:61E24F5A   Ord:  94 (005Eh)    Name: sqlite3_errcode
 Addr:61E24FCD   Ord:  95 (005Fh)    Name: sqlite3_errmsg
 Addr:61E2B08E   Ord:  96 (0060h)    Name: sqlite3_errmsg16
 Addr:61E0DE45   Ord:  97 (0061h)    Name: sqlite3_errstr
 Addr:61E6FF07   Ord:  98 (0062h)    Name: sqlite3_exec
 Addr:61E210D4   Ord:  99 (0063h)    Name: sqlite3_expanded_sql
 Addr:61E033EC   Ord: 100 (0064h)    Name: sqlite3_expired
 Addr:61E24F95   Ord: 101 (0065h)    Name: sqlite3_extended_errcode
 Addr:61E05A9B   Ord: 102 (0066h)    Name: sqlite3_extended_result_codes
 Addr:61E1A856   Ord: 103 (0067h)    Name: sqlite3_file_control
 Addr:61E05AF2   Ord: 104 (0068h)    Name: sqlite3_filename_database
 Addr:61E09829   Ord: 105 (0069h)    Name: sqlite3_filename_journal
 Addr:61E09858   Ord: 106 (006Ah)    Name: sqlite3_filename_wal
 Addr:61E542B8   Ord: 107 (006Bh)    Name: sqlite3_finalize
 Addr:61E0AA0B   Ord: 108 (006Ch)    Name: sqlite3_free
 Addr:61E0B350   Ord: 109 (006Dh)    Name: sqlite3_free_filename
 Addr:61E0B303   Ord: 110 (006Eh)    Name: sqlite3_free_table
 Addr:61EAEBA0   Ord: 111 (006Fh)    Name: sqlite3_fts3_may_be_corrupt
 Addr:61EAEA18   Ord: 112 (0070h)    Name: sqlite3_fts5_may_be_corrupt
 Addr:61E05A8A   Ord: 113 (0071h)    Name: sqlite3_get_autocommit
 Addr:61E034AA   Ord: 114 (0072h)    Name: sqlite3_get_auxdata
 Addr:61E85A82   Ord: 115 (0073h)    Name: sqlite3_get_table
 Addr:61EA3F97   Ord: 116 (0074h)    Name: sqlite3_global_recover
 Addr:61E32C96   Ord: 117 (0075h)    Name: sqlite3_hard_heap_limit64
 Addr:61E3260E   Ord: 118 (0076h)    Name: sqlite3_initialize
 Addr:61E08566   Ord: 119 (0077h)    Name: sqlite3_interrupt
 Addr:61E12C89   Ord: 120 (0078h)    Name: sqlite3_keyword_check
 Addr:61E04DDB   Ord: 121 (0079h)    Name: sqlite3_keyword_count
 Addr:61E04DA6   Ord: 122 (007Ah)    Name: sqlite3_keyword_name
 Addr:61E05578   Ord: 123 (007Bh)    Name: sqlite3_last_insert_rowid
 Addr:61E05516   Ord: 124 (007Ch)    Name: sqlite3_libversion
 Addr:61E05520   Ord: 125 (007Dh)    Name: sqlite3_libversion_number
 Addr:61E059CB   Ord: 126 (007Eh)    Name: sqlite3_limit
 Addr:61E42392   Ord: 127 (007Fh)    Name: sqlite3_load_extension
 Addr:61E22B27   Ord: 128 (0080h)    Name: sqlite3_log
 Addr:61E32D24   Ord: 129 (0081h)    Name: sqlite3_malloc
 Addr:61E33DEC   Ord: 130 (0082h)    Name: sqlite3_malloc64
 Addr:61E30A62   Ord: 131 (0083h)    Name: sqlite3_memory_alarm
 Addr:61E24DDD   Ord: 132 (0084h)    Name: sqlite3_memory_highwater
 Addr:61E24DAD   Ord: 133 (0085h)    Name: sqlite3_memory_used
 Addr:61E405A8   Ord: 134 (0086h)    Name: sqlite3_mprintf
 Addr:61E017A0   Ord: 135 (0087h)    Name: sqlite3_msize
 Addr:61E32B6E   Ord: 136 (0088h)    Name: sqlite3_mutex_alloc
 Addr:61E01743   Ord: 137 (0089h)    Name: sqlite3_mutex_enter
 Addr:61E01730   Ord: 138 (008Ah)    Name: sqlite3_mutex_free
 Addr:61E0176B   Ord: 139 (008Bh)    Name: sqlite3_mutex_leave
 Addr:61E01756   Ord: 140 (008Ch)    Name: sqlite3_mutex_try
 Addr:61E035B8   Ord: 141 (008Dh)    Name: sqlite3_next_stmt
 Addr:61EA3E82   Ord: 142 (008Eh)    Name: sqlite3_open
 Addr:61EA3EB5   Ord: 143 (008Fh)    Name: sqlite3_open16
 Addr:61EA3E9D   Ord: 144 (0090h)    Name: sqlite3_open_v2
 Addr:61E32205   Ord: 145 (0091h)    Name: sqlite3_os_end
 Addr:61E32AA7   Ord: 146 (0092h)    Name: sqlite3_os_init
 Addr:61E43C6B   Ord: 147 (0093h)    Name: sqlite3_overload_function
 Addr:61E806E0   Ord: 148 (0094h)    Name: sqlite3_prepare
 Addr:61E81288   Ord: 149 (0095h)    Name: sqlite3_prepare16
 Addr:61E812AF   Ord: 150 (0096h)    Name: sqlite3_prepare16_v2
 Addr:61E812D6   Ord: 151 (0097h)    Name: sqlite3_prepare16_v3
 Addr:61E8070E   Ord: 152 (0098h)    Name: sqlite3_prepare_v2
 Addr:61E80B62   Ord: 153 (0099h)    Name: sqlite3_prepare_v3
 Addr:61E32216   Ord: 154 (009Ah)    Name: sqlite3_preupdate_count
 Addr:61E32234   Ord: 155 (009Bh)    Name: sqlite3_preupdate_depth
 Addr:61EA3F55   Ord: 156 (009Ch)    Name: sqlite3_preupdate_hook
 Addr:61E32256   Ord: 157 (009Dh)    Name: sqlite3_preupdate_new
 Addr:61E4E419   Ord: 158 (009Eh)    Name: sqlite3_preupdate_old
 Addr:61E0585E   Ord: 159 (009Fh)    Name: sqlite3_profile
 Addr:61E05747   Ord: 160 (00A0h)    Name: sqlite3_progress_handler
 Addr:61E46B88   Ord: 161 (00A1h)    Name: sqlite3_randomness
 Addr:61E376AA   Ord: 162 (00A2h)    Name: sqlite3_realloc
 Addr:61E38B36   Ord: 163 (00A3h)    Name: sqlite3_realloc64
 Addr:61E01788   Ord: 164 (00A4h)    Name: sqlite3_release_memory
 Addr:61E56F76   Ord: 165 (00A5h)    Name: sqlite3_reset
 Addr:61EA37CF   Ord: 166 (00A6h)    Name: sqlite3_reset_auto_extension
 Addr:61E171F1   Ord: 167 (00A7h)    Name: sqlite3_result_blob
 Addr:61E17881   Ord: 168 (00A8h)    Name: sqlite3_result_blob64
 Addr:61E13158   Ord: 169 (00A9h)    Name: sqlite3_result_double
 Addr:61E16F29   Ord: 170 (00AAh)    Name: sqlite3_result_error
 Addr:61E170A9   Ord: 171 (00ABh)    Name: sqlite3_result_error16
 Addr:61E170D2   Ord: 172 (00ACh)    Name: sqlite3_result_error_code
 Addr:61E10958   Ord: 173 (00ADh)    Name: sqlite3_result_error_nomem
 Addr:61E1715E   Ord: 174 (00AEh)    Name: sqlite3_result_error_toobig
 Addr:61E0AED4   Ord: 175 (00AFh)    Name: sqlite3_result_int
 Addr:61E0AF0F   Ord: 176 (00B0h)    Name: sqlite3_result_int64
 Addr:61E0AF3A   Ord: 177 (00B1h)    Name: sqlite3_result_null
 Addr:61E13012   Ord: 178 (00B2h)    Name: sqlite3_result_pointer
 Addr:61E0345E   Ord: 179 (00B3h)    Name: sqlite3_result_subtype
 Addr:61E172DA   Ord: 180 (00B4h)    Name: sqlite3_result_text
 Addr:61E1787B   Ord: 181 (00B5h)    Name: sqlite3_result_text16
 Addr:61E1783D   Ord: 182 (00B6h)    Name: sqlite3_result_text16be
 Addr:61E1785C   Ord: 183 (00B7h)    Name: sqlite3_result_text16le
 Addr:61E178BD   Ord: 184 (00B8h)    Name: sqlite3_result_text64
 Addr:61E16AB4   Ord: 185 (00B9h)    Name: sqlite3_result_value
 Addr:61E133B7   Ord: 186 (00BAh)    Name: sqlite3_result_zeroblob
 Addr:61E0B01D   Ord: 187 (00BBh)    Name: sqlite3_result_zeroblob64
 Addr:61E05936   Ord: 188 (00BCh)    Name: sqlite3_rollback_hook
 Addr:61EA3F9E   Ord: 189 (00BDh)    Name: sqlite3_rtree_geometry_callback
 Addr:61EA401C   Ord: 190 (00BEh)    Name: sqlite3_rtree_query_callback
 Addr:61E86065   Ord: 191 (00BFh)    Name: sqlite3_serialize
 Addr:61E03C24   Ord: 192 (00C0h)    Name: sqlite3_set_authorizer
 Addr:61E15E97   Ord: 193 (00C1h)    Name: sqlite3_set_auxdata
 Addr:61E05586   Ord: 194 (00C2h)    Name: sqlite3_set_last_insert_rowid
 Addr:61EA3822   Ord: 195 (00C3h)    Name: sqlite3_shutdown
 Addr:61E32A0D   Ord: 196 (00C4h)    Name: sqlite3_sleep
 Addr:61E229BB   Ord: 197 (00C5h)    Name: sqlite3_snprintf
 Addr:61E32C72   Ord: 198 (00C6h)    Name: sqlite3_soft_heap_limit
 Addr:61E32B9D   Ord: 199 (00C7h)    Name: sqlite3_soft_heap_limit64
 Addr:61E0855C   Ord: 200 (00C8h)    Name: sqlite3_sourceid
 Addr:61E035F1   Ord: 201 (00C9h)    Name: sqlite3_sql
 Addr:61E24D55   Ord: 202 (00CAh)    Name: sqlite3_status
 Addr:61E24CC5   Ord: 203 (00CBh)    Name: sqlite3_status64
 Addr:61E6F227   Ord: 204 (00CCh)    Name: sqlite3_step
 Addr:61E03599   Ord: 205 (00CDh)    Name: sqlite3_stmt_busy
 Addr:61E0357F   Ord: 206 (00CEh)    Name: sqlite3_stmt_isexplain
 Addr:61E03562   Ord: 207 (00CFh)    Name: sqlite3_stmt_readonly
 Addr:61E11166   Ord: 208 (00D0h)    Name: sqlite3_stmt_status
 Addr:61E197C9   Ord: 209 (00D1h)    Name: sqlite3_str_append
 Addr:61E197FE   Ord: 210 (00D2h)    Name: sqlite3_str_appendall
 Addr:61E1456B   Ord: 211 (00D3h)    Name: sqlite3_str_appendchar
 Addr:61E2077B   Ord: 212 (00D4h)    Name: sqlite3_str_appendf
 Addr:61E017BF   Ord: 213 (00D5h)    Name: sqlite3_str_errcode
 Addr:61E16178   Ord: 214 (00D6h)    Name: sqlite3_str_finish
 Addr:61E017D4   Ord: 215 (00D7h)    Name: sqlite3_str_length
 Addr:61E33E12   Ord: 216 (00D8h)    Name: sqlite3_str_new
 Addr:61E0AAFA   Ord: 217 (00D9h)    Name: sqlite3_str_reset
 Addr:61E017E5   Ord: 218 (00DAh)    Name: sqlite3_str_value
 Addr:61E1F3C7   Ord: 219 (00DBh)    Name: sqlite3_str_vappendf
 Addr:61E0A5E7   Ord: 220 (00DCh)    Name: sqlite3_strglob
 Addr:61E01964   Ord: 221 (00DDh)    Name: sqlite3_stricmp
 Addr:61E0A602   Ord: 222 (00DEh)    Name: sqlite3_strlike
 Addr:61E0198A   Ord: 223 (00DFh)    Name: sqlite3_strnicmp
 Addr:61E059BA   Ord: 224 (00E0h)    Name: sqlite3_system_errno
 Addr:61E8578B   Ord: 225 (00E1h)    Name: sqlite3_table_column_metadata
 Addr:61EC4024   Ord: 226 (00E2h)    Name: sqlite3_temp_directory
 Addr:61EA3189   Ord: 227 (00E3h)    Name: sqlite3_test_control
 Addr:61E05A96   Ord: 228 (00E4h)    Name: sqlite3_thread_cleanup
 Addr:61E0552A   Ord: 229 (00E5h)    Name: sqlite3_threadsafe
 Addr:61E055C6   Ord: 230 (00E6h)    Name: sqlite3_total_changes
 Addr:61E057B5   Ord: 231 (00E7h)    Name: sqlite3_trace
 Addr:61E05806   Ord: 232 (00E8h)    Name: sqlite3_trace_v2
 Addr:61E12890   Ord: 233 (00E9h)    Name: sqlite3_transfer_bindings
 Addr:61E055D1   Ord: 234 (00EAh)    Name: sqlite3_txn_state
 Addr:61E058F4   Ord: 235 (00EBh)    Name: sqlite3_update_hook
 Addr:61E097AA   Ord: 236 (00ECh)    Name: sqlite3_uri_boolean
 Addr:61E119DD   Ord: 237 (00EDh)    Name: sqlite3_uri_int64
 Addr:61E097DD   Ord: 238 (00EEh)    Name: sqlite3_uri_key
 Addr:61E09753   Ord: 239 (00EFh)    Name: sqlite3_uri_parameter
 Addr:61E03474   Ord: 240 (00F0h)    Name: sqlite3_user_data
 Addr:61E2146C   Ord: 241 (00F1h)    Name: sqlite3_value_blob
 Addr:61E212EB   Ord: 242 (00F2h)    Name: sqlite3_value_bytes
 Addr:61E213BC   Ord: 243 (00F3h)    Name: sqlite3_value_bytes16
 Addr:61E1F3BB   Ord: 244 (00F4h)    Name: sqlite3_value_double
 Addr:61E32FA3   Ord: 245 (00F5h)    Name: sqlite3_value_dup
 Addr:61E0B092   Ord: 246 (00F6h)    Name: sqlite3_value_free
 Addr:61E0344C   Ord: 247 (00F7h)    Name: sqlite3_value_frombind
 Addr:61E0C477   Ord: 248 (00F8h)    Name: sqlite3_value_int
 Addr:61E0C484   Ord: 249 (00F9h)    Name: sqlite3_value_int64
 Addr:61E03433   Ord: 250 (00FAh)    Name: sqlite3_value_nochange
 Addr:61E305AE   Ord: 251 (00FBh)    Name: sqlite3_value_numeric_type
 Addr:61E11827   Ord: 252 (00FCh)    Name: sqlite3_value_pointer
 Addr:61E03409   Ord: 253 (00FDh)    Name: sqlite3_value_subtype
 Addr:61E21433   Ord: 254 (00FEh)    Name: sqlite3_value_text
 Addr:61E22598   Ord: 255 (00FFh)    Name: sqlite3_value_text16
 Addr:61E223C5   Ord: 256 (0100h)    Name: sqlite3_value_text16be
 Addr:61E223D6   Ord: 257 (0101h)    Name: sqlite3_value_text16le
 Addr:61E0341E   Ord: 258 (0102h)    Name: sqlite3_value_type
 Addr:61EC2E20   Ord: 259 (0103h)    Name: sqlite3_version
 Addr:61E329AA   Ord: 260 (0104h)    Name: sqlite3_vfs_find
 Addr:61E32A44   Ord: 261 (0105h)    Name: sqlite3_vfs_register
 Addr:61E32B2E   Ord: 262 (0106h)    Name: sqlite3_vfs_unregister
 Addr:61E3FAC4   Ord: 263 (0107h)    Name: sqlite3_vmprintf
 Addr:61E2295F   Ord: 264 (0108h)    Name: sqlite3_vsnprintf
 Addr:61E29769   Ord: 265 (0109h)    Name: sqlite3_vtab_collation
 Addr:61E24E0C   Ord: 266 (010Ah)    Name: sqlite3_vtab_config
 Addr:61E0348F   Ord: 267 (010Bh)    Name: sqlite3_vtab_nochange
 Addr:61E04568   Ord: 268 (010Ch)    Name: sqlite3_vtab_on_conflict
 Addr:61E0DE9D   Ord: 269 (010Dh)    Name: sqlite3_wal_autocheckpoint
 Addr:61E538C9   Ord: 270 (010Eh)    Name: sqlite3_wal_checkpoint
 Addr:61E53885   Ord: 271 (010Fh)    Name: sqlite3_wal_checkpoint_v2
 Addr:61E05978   Ord: 272 (0110h)    Name: sqlite3_wal_hook
 Addr:61E30BE6   Ord: 273 (0111h)    Name: sqlite3_win32_is_nt
 Addr:61EA35DE   Ord: 274 (0112h)    Name: sqlite3_win32_mbcs_to_utf8
 Addr:61EA3607   Ord: 275 (0113h)    Name: sqlite3_win32_mbcs_to_utf8_v2
 Addr:61EA3737   Ord: 276 (0114h)    Name: sqlite3_win32_set_directory
 Addr:61EA36EB   Ord: 277 (0115h)    Name: sqlite3_win32_set_directory16
 Addr:61EA367C   Ord: 278 (0116h)    Name: sqlite3_win32_set_directory8
 Addr:61E30ACB   Ord: 279 (0117h)    Name: sqlite3_win32_sleep
 Addr:61EA35BD   Ord: 280 (0118h)    Name: sqlite3_win32_unicode_to_utf8
 Addr:61EA362D   Ord: 281 (0119h)    Name: sqlite3_win32_utf8_to_mbcs
 Addr:61EA3656   Ord: 282 (011Ah)    Name: sqlite3_win32_utf8_to_mbcs_v2
 Addr:61EA359C   Ord: 283 (011Bh)    Name: sqlite3_win32_utf8_to_unicode
 Addr:61E30A69   Ord: 284 (011Ch)    Name: sqlite3_win32_write_debug
 Addr:61EA5929   Ord: 285 (011Dh)    Name: sqlite3changegroup_add
 Addr:61EA598B   Ord: 286 (011Eh)    Name: sqlite3changegroup_add_strm
 Addr:61EA59F1   Ord: 287 (011Fh)    Name: sqlite3changegroup_delete
 Addr:61EA5B40   Ord: 288 (0120h)    Name: sqlite3changegroup_new
 Addr:61EA596F   Ord: 289 (0121h)    Name: sqlite3changegroup_output
 Addr:61EA59D1   Ord: 290 (0122h)    Name: sqlite3changegroup_output_strm
 Addr:61EA581C   Ord: 291 (0123h)    Name: sqlite3changeset_apply
 Addr:61EA58DB   Ord: 292 (0124h)    Name: sqlite3changeset_apply_strm
 Addr:61EA57AF   Ord: 293 (0125h)    Name: sqlite3changeset_apply_v2
 Addr:61EA586A   Ord: 294 (0126h)    Name: sqlite3changeset_apply_v2_strm
 Addr:61EA5AC5   Ord: 295 (0127h)    Name: sqlite3changeset_concat
 Addr:61EA5A4A   Ord: 296 (0128h)    Name: sqlite3changeset_concat_strm
 Addr:61EA4AB3   Ord: 297 (0129h)    Name: sqlite3changeset_conflict
 Addr:61EA4B16   Ord: 298 (012Ah)    Name: sqlite3changeset_finalize
 Addr:61EA4AF3   Ord: 299 (012Bh)    Name: sqlite3changeset_fk_conflicts
 Addr:61EA571A   Ord: 300 (012Ch)    Name: sqlite3changeset_invert
 Addr:61EA5759   Ord: 301 (012Dh)    Name: sqlite3changeset_invert_strm
 Addr:61E0EBC9   Ord: 302 (012Eh)    Name: sqlite3changeset_new
 Addr:61EA4A4C   Ord: 303 (012Fh)    Name: sqlite3changeset_next
 Addr:61E0EB8F   Ord: 304 (0130h)    Name: sqlite3changeset_old
 Addr:61EA4A63   Ord: 305 (0131h)    Name: sqlite3changeset_op
 Addr:61EA4A93   Ord: 306 (0132h)    Name: sqlite3changeset_pk
 Addr:61EA4984   Ord: 307 (0133h)    Name: sqlite3changeset_start
 Addr:61EA49E3   Ord: 308 (0134h)    Name: sqlite3changeset_start_strm
 Addr:61EA49B5   Ord: 309 (0135h)    Name: sqlite3changeset_start_v2
 Addr:61EA4A18   Ord: 310 (0136h)    Name: sqlite3changeset_start_v2_strm
 Addr:61EA5B49   Ord: 311 (0137h)    Name: sqlite3rebaser_configure
 Addr:61EA5A16   Ord: 312 (0138h)    Name: sqlite3rebaser_create
 Addr:61EA5C69   Ord: 313 (0139h)    Name: sqlite3rebaser_delete
 Addr:61EA5B99   Ord: 314 (013Ah)    Name: sqlite3rebaser_rebase
 Addr:61EA5C00   Ord: 315 (013Bh)    Name: sqlite3rebaser_rebase_strm
 Addr:61EA4213   Ord: 316 (013Ch)    Name: sqlite3session_attach
 Addr:61EA4837   Ord: 317 (013Dh)    Name: sqlite3session_changeset
 Addr:61EA484E   Ord: 318 (013Eh)    Name: sqlite3session_changeset_strm
 Addr:61EA5C8E   Ord: 319 (013Fh)    Name: sqlite3session_config
 Addr:61EA4099   Ord: 320 (0140h)    Name: sqlite3session_create
 Addr:61EA4165   Ord: 321 (0141h)    Name: sqlite3session_delete
 Addr:61EA435F   Ord: 322 (0142h)    Name: sqlite3session_diff
 Addr:61EA48B5   Ord: 323 (0143h)    Name: sqlite3session_enable
 Addr:61EA48F0   Ord: 324 (0144h)    Name: sqlite3session_indirect
 Addr:61EA492B   Ord: 325 (0145h)    Name: sqlite3session_isempty
 Addr:61EA4976   Ord: 326 (0146h)    Name: sqlite3session_memory_used
 Addr:61EA489B   Ord: 327 (0147h)    Name: sqlite3session_patchset
 Addr:61EA4873   Ord: 328 (0148h)    Name: sqlite3session_patchset_strm
 Addr:61EA41F8   Ord: 329 (0149h)    Name: sqlite3session_table_filter


1. Основные функции библиотеки sqlite3.dll

Функции SQLite позволяют выполнять следующий набор операций:


1. Создание в базе-данных новой таблицы;
2. Заполнение таблицы записями;
3. Чтение строк и столбцов в соответствии с заданным условием;
4. Изменение существующей информации;
5. Удаление записей из ячеек таблицы.

Из этого списка, нашим интересам удовлетворяет только пункт(3), поскольку мы планируем вытягивать из баз-данных кукисы и пароли интернет-браузеров. Если рассматривать возможности программирования всех операций, то основной посыл статьи уйдёт на пятый план, так-что лучше остановимся на одном. По сути, поняв общий принцип формирования запросов, без особого труда можно будет выполнять любые операции – тут главное разобраться, что такое запрос и кто его выполняет.


1.1. sqlite3_open_v2(), sqlite3_close()

База – это файл данных. Согласно общепринятому алгоритму работы с файлами, для начала базу нужно открыть функцией sqlite3_open_v2(). Во-второй этой версии, в прототип были добавлены два дополнительных параметра: flags и zVfs. Последний означает Virtual-File-System (vfs) и нам не нужен. Зато флаг даёт возможность не только открывать базу, но и создавать её. Конкретное действие определяется перечисленными ниже константами:


C-подобный:
sqlite3_open_v2 (   ;//<--- в EAX возвращает SQLITE_ОК = 0, и хэндл базы
  dbName    dd  0   ;// указатель на имя базы-данных
  dbHndl    dd  0   ;// указатель на переменную, куда возвратится хэндл
  flags     dd  0   ;// флаги открытия (чтение/запись/создание)
  zVfs      dd  0   ;// 0
);
;//*************************************
;// Флаги для операций открытия файлов
;//*************************************
SQLITE_OPEN_READONLY        = 0x0001
SQLITE_OPEN_READWRITE       = 0x0002
SQLITE_OPEN_CREATE          = 0x0004
SQLITE_OPEN_DELETEONCLOSE   = 0x0008
SQLITE_OPEN_EXCLUSIVE       = 0x0010
SQLITE_OPEN_AUTOPROXY       = 0x0020
SQLITE_OPEN_URI             = 0x0040
SQLITE_OPEN_MAIN_DB         = 0x0100
SQLITE_OPEN_TEMP_DB         = 0x0200
SQLITE_OPEN_TRANSIENT_DB    = 0x0400
SQLITE_OPEN_MAIN_JOURNAL    = 0x0800
SQLITE_OPEN_TEMP_JOURNAL    = 0x1000
SQLITE_OPEN_SUBJOURNAL      = 0x2000
SQLITE_OPEN_MASTER_JOURNAL  = 0x4000
SQLITE_OPEN_NOMUTEX         = 0x8000
SQLITE_OPEN_FULLMUTEX       = 0x10000
SQLITE_OPEN_SHAREDCACHE     = 0x20000
SQLITE_OPEN_PRIVATECACHE    = 0x40000
SQLITE_OPEN_WAL             = 0x80000

Данная функция открытия базы проделывает огромный объём работы, подготавливая контент и окружение для всех последующих функций sqlite3.dll. Она копирует содержимое базы в оперативную память ОЗУ, выстраивает локальную таблицу указателей на инфо-ячейки таблицы и многое другое. Если open_v2() предоставляет программные ресурсы, то родственная ей функция sqlite3_close() наоборот освобождает их. Однако в её вызове нет необходимости, если далее закрывается сама программа, т.к. ExitProcess() на выходе в любом случае проделывает аналогичную работу, освобождая глобальные ресурсы процесса на более низком уровне.


1.2. Операторы запросов SQLite

Значит базу открыли, и теперь нужно произвести с ней какие-либо действия. Для этого, мы должны послать ядру соответствующий запрос, который состоит как-минимум из двух операторов: SELECT и FROM (рассматриваем чтение). Об этом, прямым текстом сообщает и название языка программирования "Structured Query Language", или язык структурированных запросов. Исторически, операторы любой СУБД делятся на 4 типа, и SQLite здесь не исключение:

Операторы определения данных (Data Definition Language, DDL):

• CREATE – создаёт объект (базу, таблицу и т.д.);
• ALTER – изменяет объект;
• DROP – удаляет объект.

Операторы манипуляции данными (Data Manipulation Language, DML):
• SELECT – запрашивает (выбирает) данные из таблицы, удовлетворяющие условиям WHERE;
• INSERT – добавляет новую информацию;
• UPDATE – изменяет существующие данные;
• DELETE – удаляет данные.

Операторы определения доступа к данным (Data Control Language, DCL):
• DENY – устанавливает запрет, имеющий приоритет над разрешением;
• GRANT – разрешает определённые операции с объектом;
• REVOKE – отзывает ранее выданные разрешения.

Операторы управления транзакциями (Transaction Control Language, TCL):
• COMMIT – применяет транзакцию;
• ROLLBACK – откатывает все изменения, в контексте текущей транзакции;
• SAVEPOINT – делит транзакцию на мелкие части.

Как видим, для обычного чтения данных используется оператор SELECT, которому передаются ещё несколько уточняющих запрос аргументов – это имена столбцов в таблице (т.е. что именно интересует), имя таблицы через оператор FROM (т.е.где искать, поскольку таблиц в одной базе может быть несколько), и если нужно условие, посредством оператора WHERE. Вот пара простых примеров оформления запросов:

C-подобный:
;// прочитать все данные из таблицы "cookies"
select#1   db  'SELECT * FROM cookies',0

;// прочитать только столбцы "key" и "name" из таблицы "cookies"
select#2   db  'SELECT key, name FROM cookies',0

Для начала нам этого хватит, а с диалектом более сложных запросов мы ознакомимся в конце этой статьи. Несколько линков по теме:

Оператор SELECT:


Основные запросы SQL, которые должен знать каждый программист:




1.3. prepare() и finalize() – подготовка оператора запроса

На следующем этапе, подготовленный запрос в виде текстовой строки необходимо скомпилировать в байт-код, чем занимается синтаксический анализатор функции sqlite3_prepare_v2(). Переварив строку, эта функция модифицирует её в соответствующий формат и помещает полученный бинарник в память, а нам возвращает лишь дескриптор на него. В документации, этот дескриптор называют "STMT", что означает Prepared-Statement-Object (готовый объект заявления).

В последующих операциях чтения, мы должны будем передавать этот объект всем функциям-исполнения конкретно данного запроса. Если-же захотим сменить запрос на другой (с иными операторами), то сначала нужно аннулировать предыдущий функцией sqlite3_finalize(), и только потом оформлять новый, обратно функцией prepare_v2(). Вот её прототип:


C-подобный:
sqlite3_prepare_v2 (  ;//<--- на выходе 0 в EAX означает OK!
  dbHndl      dd  0   ;// хэндл базы от sqlite_open_v2()
  zSql        dd  0   ;// указатель на строку операторов запроса SQLite
  nByte       dd  0   ;// длина запроса в байтах (-1 = до терминального нуля)
  pStmt       dd  0   ;// линк на переменную, куда вернётся дескриптор запроса
  pTail       dd  0   ;// 0 = хвост запроса (нам не нужен)
);

В базовой версии этой функции необходимо было всегда финализировать запросы, перед тем-как оформлять новые. Но в усовершенствованной версии(2) необходимость в этом отпала, т.к. автор посчитал данное действо само-собой разумеющимся, и зашил его внутрь исполняющих запрос функций. Теперь, если запрос отрабатывает до конца, то сбрасывать его не нужно. Однако если мы хотим прервать запрос на половине исполнения (например планировали чтение всех строк базы, а потом решили остановиться на 10-ой), то вызов sqlite3_finalize() в этом случае обязателен. Данный нюанс способен изрядно попортить нервы, поэтому не сбрасывайте его со-счетов. По большому счёту, в финализации отработанных запросов нет ничего страшного, поэтому можно действовать по усмотрению.


1.4. step() и exec() – исполнение запроса

Непосредственным исполнением предписанных в запросах операций занимаются две функции – это sqlite3_step() и sqlite3_exec(). Первая немного предпочтительней, поскольку позволяет более тонко контролировать процесс исполнения, хотя для чтения каждой из строк таблицы её нужно вызывать в цикле. Это означает, что на каждом шаге Step, функция просто перемещает указатель на следующую строку, и если это не последняя, то возвращает в регистре EAX константу SQLITE_ROW=64h (есть ещё строки), иначе SQLITE_DONE=65h (выполнено и достигли конца таблицы).

Что делать дальше с этой строкой определяют уже
функции sqlite3_step(). Например, сместившись на очередную позицию, мы можем запросить внутри цикла следующие из них, которые будем использовать в примерах ниже:

sqlite3_column_type() – возвращает константу, определяющую тип данных в столбце;
sqlite3_column_text() – возвращает указатель на строковые данные столбца;
sqlite3_column_int() – возвращает значение (целое 32-бит число) столбца в текущей строке;
sqlite3_column_blob() – возвращает указатель на массив двоичных данных столбца;
sqlite3_column_bytes() – возвращает размер данных в текущей ячейки;

Прототипы у всех этих методов одинаковые – в первом аргументе передаём дескриптор скомпилированного функцией sqlite3_prepare_v2() запроса, а во-втором – индекс столбца для чтения (он привязан к последовательности в запросе, а не к порядковому номеру столбца в глобальной таблице). Здесь уместным будет замечание, что столбцы в таблицах любой базы-данных нумеруются начиная с нуля, а строки с единицы. Метод sqlite3_column_type() может возвращать одну из перечисленных ниже констант:

dType.png


Как видим, SQLite не имеет отдельного класса для хранения даты/времени – они определяются в виде значений INTEGER, FLOAT или TEXT. При этом предпочтительный вариант именно TEXT, поскольку при помощи операторов ASC/DESC позволяет сортировать строки по дате. В остальных вариантах, эта возможность не поддерживается. Вот как они представляются в ячейках таблицы. Здесь можно ознакомиться с деталями:

• TEXT – дата в формате "YYYY-MM-DD HH:MM:SS.SSS"
• FLOAT – число дней, прошедших с полудня в Гринвиче 24 ноября 4714 до нашей эры.
• INTEGER – количество секунд с момента 1970-01-01 00:00:00 UTC.

Вторая функция исполнения запросов sqlite3_exec() присваивает себе право проделывать всю работу без нашего с вами участия. Её можно рассматривать как авто-Step, без применения циклов. Интерфейс представляет собой оболочку "три-в-одном", внутри которой вызываются сразу три рассмотренные выше функции: prepare(), step() и finalize(). Это сокращает исходный код приложения, зато лишает нас возможности контролировать процесс. Прототип данной функции лежит на официальном сайте по линку.


2.0. Практика – собираем информацию о базе-данных

Теперь посмотрим, как выглядит всё это хозяйство на практике. В примере я сброшу на консоль общую информацию о базе SQLite, в которой хранятся кукисы браузера Chrome. Чтобы не мешать работе браузера, сначала нужно будет сформировать путь до его кукисов, и скопировать их в свою директорию. Функция из shell32.dll SHGetFolderPathA() с ключом CSIDL_LOCAL_APPDATA возвратит нам папку юзера ..\AppData\Local, к которой добавим строку с адресом кукисов хрома. Не смотря на то, что функция устаревшая, её не оказалось в инклуде импорта FASM\INCLUDE\API\SHELL32.INC, поэтому добавим её туда самостоятельно. Вот исходник и результат его работы:


C-подобный:
format pe console
include 'win32ax.inc'
include 'equates\sqlite3.inc'
entry start
;//------------
.data
cookDbName     db  'Cookies.db',0     ;//<--- имя для скопированной базы
cookHndl       dd  0
cookPath       db  128 dup(0)
szCook         db  '\Google\Chrome\User Data\Default\Cookies',0

typeTable      dd  0,szInt,szFloat,szText,szBlob,szNull    ;//<--- таблица с именами типов данных
szInt          db  'INTEGER',0
szFloat        db  'FLOAT',0
szText         db  'TEXT',0
szBlob         db  'BLOB',0
szNull         db  'NULL',0

select         db  'SELECT * FROM cookies',0     ;//<---//**** строка запроса с операторами ****//
index          dd  0         ;// будет индексом столбца
stmt           dd  0         ;// дескриптор скомпилированного запроса
buff           db  0         ;// для производственных нужд..
;//------------
.code
start:   invoke  SetConsoleTitle,<'*** Chrome cookies DB info ***',0>

;// Формируем путь и копируем файл кукисов из Хрома
         invoke  SHGetFolderPathA,0,CSIDL_LOCAL_APPDATA,0,0,cookPath
         invoke  lstrcat,cookPath,szCook
         invoke  CopyFile,cookPath,cookDbName,0
         or      eax,eax           ;//<----------- ошибка?
         jne     @ok
        cinvoke  printf,<10,' ERROR! Google path not found.',0>
         jmp     @exit

@ok:    cinvoke  printf,<10,' Cookies path: %s',10,0>,cookPath

;//****************************************************************
;//*************  Работа с таблицей "SQLite"  *********************
;//****************************************************************
;// Подключаемся к базе и оформляем запрос
        cinvoke  sqlite3_open_v2,cookDbName,cookHndl,SQLITE_OPEN_READONLY,0
        cinvoke  sqlite3_prepare_v2,[cookHndl],select,-1,stmt,0

;// Подпрограммы возвращают версию DLL, имя базы и таблицы, кол-во столбцов.
        cinvoke  sqlite3_libversion
        cinvoke  printf,<10,' DLL library..:  v%s',0>,eax

        cinvoke  sqlite3_column_database_name,[stmt],[index]
        cinvoke  printf,<10,' Database name:  %s',0>,eax

        cinvoke  sqlite3_column_table_name,[stmt],[index]
        cinvoke  printf,<10,' Table name...:  %s',0>,eax

        cinvoke  sqlite3_column_count,[stmt]
        cinvoke  printf,<10,' Table columns:  %d',10,\
                         10,' Columns list...',10,0>,eax

;// Цикл Step с выводом имени столбца, и типом его значений
@nextColumn:
        cinvoke  sqlite3_column_origin_name,[stmt],[index]
         cmp     eax,0
         je      @exit
        cinvoke  printf,<10,' %3d. %-16s',0>,[index],eax  ;// числа форматируют отступ

        cinvoke  sqlite3_step,[stmt]                  ;// функция,
        cinvoke  sqlite3_column_type,[stmt],[index]   ;//  ..и её метод.
         mov     esi,typeTable
         shl     eax,2
         mov     eax,[esi+eax]
        cinvoke  printf,<' %s',0>,eax

         inc     [index]          ;// следующий индекс
         jmp     @nextColumn      ;// повторить для всех столбцов..

@exit:  cinvoke  sqlite3_finalize,[stmt]
        cinvoke  _getch
        cinvoke  exit,0
;//------------
section '.idata' import data readable
library  kernel32,'kernel32.dll',shell32,'shell32.dll',\
         msvcrt,'msvcrt.dll',sqlite3,'sqlite3.dll'

include  'api\kernel32.inc'
include  'api\shell32.inc'
include  'api\sqliteAPI.inc'  ;//<--- импорт API
include  'api\msvcrt.inc'     ;// ^^^^^^^^^^

DB_struct.png


Так, не открывая базу в стороннем редакторе, мы получили имена столбцов и если это шелл-код, он может сформировать строку запроса прямо на-лету. Ясно, что структура таблицы кукисов известна всем, но если мы столкнёмся с какой-нибудь базой на удалённом узле, то "слепое" вычисление имени столбцов (и типов данных в них) может сыграть нам на руку. К примеру обнаружив поле BLOB (Binary-Long-Object, массив двоичных данных) можно сделать вывод, что перед нами зашифрованное содержимое, и это может быть пароль или другая конфиденциальная инфа.


2.1. Практика – чтение "cookies" браузеров

Теперь чуть усложним задачу, и попробуем изъять из этой базы все кукисы. Читать будем обозначенные на скрине выше поля, но сначала дадим короткое определение, что такое вообще "cookie", какие они бывают, и зачем нужны.
можно найти более развёрнутый ответ на эти вопросы, от самих разрабов Хром.
-----------------------

Кукисы – это текстовые файлы у нас на компьютерах, в которых хранится инфа о наших предыдущих действиях на сайтах. Когда мы совершаем какое-то действие (например, вводим пароли входа в аккаунт), сервер сбрасывает эту информацию в куки и отправляет браузеру вместе со страницей. Теперь, когда мы следующий раз заходим на тот-же сайт или страницу, браузер отправляет куки обратно. Они бывают временными и постоянными – в браузерах Хром, время их жизни определяет значение в столбце "expires_utc". Постоянные куки остаются на компьютере, когда мы закрываем вкладку сайта, а временные удаляются.

По сути куки не опасны – это обычный текст. Они не могут запускать процессы и взаимодействовать с ОС как-бы то нибыло. Но некоторые подозрительные личности в маске джокера могут попытаться украсть их, чтобы отследить наши действия в сети, или зайти в аккаунт без авторизации. Именно это и представляет потенциальную угрозу в хранение кукисов. Кроме входов в аккаунты они умеют запоминать:


• предпочтения юзеров, например язык/валюту/шрифт;
• товары, которые мы просматривали или добавили в корзину;
• текст, который мы вводили на сайте раньше;
• IP-адрес и местоположение пользователя;
• время посещения сайта;
• версию ОС и браузера;
• клики и переходы.

Согласно общепринятым правилам, серверы могут высылать кукисы строго предопределённого типа, которые можно распознать по их именам:

_ga – кукис аналитики (стистика и прочее);
_gads, _gas_ – реклама на партнёрских сайтах;
_gcl_ – отслеживание конверсий;
CGIC – ускоряет действия в поисковой строке (интерактивный поиск);
DSID – киллер рекламы для авторизированных юзеров;
IDE, ANID – показ рекламы юзерам без реги;
NID, VISITOR_INFO1_LIVE – идентификатор настроек и предпочтений юзера (язык, шрифт и т.д.);
PREF, YSC, pm_sess – предотвращение спама, и настройки медиа-проигрывателя в ютубе (громкость, размер и т.д.);
SID, HSID – цифровая подписью и зашифрованные сведения об аккаунте Google.

Ну и теперь немного о самом коде..
Поскольку значения всех столбцов таблицы нам не интересны (см.скрин выше), то в строке запроса перечисляем только нужные из них. То-есть запрос будет такого вида:

select db 'SELECT host_key, name FROM cookies',0

Кстати макс.значение индекса столбцов для методов функции sqlite3_step() в этом случае будет =1 (отсчёт с нуля). На запрос такого рода получим всего по два значения из каждой строки – это имя хоста и кукиса. Раз-уж разборки с паролем мы оставили для сл.части статьи, то прицепом к именам можно вывести хотя-бы время создания/окончания действия кукиса. Значит добавим к этому запросу ещё два столбца – creation_utc и expires_utc. Но здесь буйком всплывает проблема преобразования значения INTEGER в строку даты/времени.

Одной из примечательных особенностей языка SQL является возможность оформлять вложенные запросы – т.е. в основной запрос помещаем дочерний под-запрос. Немного попыхтев при его обработке, ядро выдаст результаты обоих, и остаётся вывести их на консоль в подобающем виде. В данном случае, для преобразования времени мы воспользуемся этой фишкой и вложим в запрос целую функцию SQLite для работы с датами strftime(). Она чем-то напоминает printf() из msvcrt.dll и ожидает в аргументе спецификаторы типа %s. В конечном итоге, оформленный по этим правилам строка запроса будет выглядеть так, и мы получим время в текстовом виде:


C-подобный:
select   db  "SELECT host_key, name,"

         db  "strftime('%Y.%m.%d %H:%M',"
         db  "creation_utc /1000000 + (strftime('%s','1601-01-01')),'unixepoch','localtime'),"

         db  "strftime('%Y.%m.%d %H:%M',"
         db  " expires_utc /1000000 + (strftime('%s','1601-01-01')),'unixepoch','localtime')"
         db  "FROM cookies",0

В остальном – всё довольно прозрачно. Значит делаем Step и проверяем его выхлоп на SQLITE_ROW, что означает наличие следующих строк в таблице. Теперь, внутри цикла зовём метод sqlite3_column_text() и в регистре EAX получаем указатель на данные в текстовом виде, текущего столбца и строки. Вызываем этот-же метод для всех столбцов, которые перечислены в запросе. При этом не забываем каждый раз добавлять к индексу 1. Можно предусмотреть и переменную для подсчёта обработанных строк – это будет счётчиком кукисов в базе. Вот пример такого алго:

C-подобный:
format pe console
include 'win32ax.inc'
include 'equates\sqlite3.inc'
entry start
;//------------
.data
cookPath       db  128 dup(0)
szCook         db  '\Google\Chrome\User Data\Default\Cookies',0

cookDbName     db  'Cookies.db',0
cookHndl       dd  0

select         db  "SELECT host_key, name,"
               db  "strftime('%Y.%m.%d %H:%M',"
               db  "creation_utc /1000000 + (strftime('%s','1601-01-01')),'unixepoch','localtime'),"

               db  "strftime('%Y.%m.%d %H:%M',"
               db  " expires_utc /1000000 + (strftime('%s','1601-01-01')),'unixepoch','localtime')"
               db  "FROM cookies",0

counter        dd  0
stmt           dd  0
buff           db  0
;//------------
.code
start:   invoke  SetConsoleTitle,<'*** Chrome cookies list ***',0>

;// Формируем путь и копируем файл кукисов из Хрома
         invoke  SHGetFolderPathA,0,CSIDL_LOCAL_APPDATA,0,0,cookPath
         invoke  lstrcat,cookPath,szCook

         invoke  CopyFile,cookPath,cookDbName,0
         or      eax,eax           ;//<----------- ошибка?
         jne     @ok
        cinvoke  printf,<10,' ERROR! Google path not found.',0>
         jmp     @exit
@ok:    cinvoke  printf,<10,' Cookies path: %s',10,0>,cookPath

;//****************************************************************
;//*************  Работа с таблицей "SQLite"  *********************
;//****************************************************************
;// Подключаемся к базе и оформляем запрос
        cinvoke  sqlite3_open_v2,cookDbName,cookHndl,SQLITE_OPEN_READONLY,0
        cinvoke  sqlite3_prepare_v2,[cookHndl],select,-1,stmt,0

;// Цикл чтения и обработки строк таблицы
@@:     cinvoke  sqlite3_step,[stmt]
         cmp     eax,SQLITE_ROW        ;// есть ещё строки?
         jne     @free                 ;// нет – на выход.

        cinvoke  sqlite3_column_text,[stmt],0       ;//<--- индекс(0) в запросе = host_key
        cinvoke  printf,<10,\
                         10,' Host.......:  %s',0>,eax

        cinvoke  sqlite3_column_text,[stmt],1       ;//<--- индекс(1) = name
        cinvoke  printf,<10,' Cookie name:  %s',0>,eax

        cinvoke  sqlite3_column_text,[stmt],2       ;//<--- индекс(2) = creation_utc
        cinvoke  printf,<10,' LifeTime...:  %s',0>,eax

        cinvoke  sqlite3_column_text,[stmt],3       ;//<--- индекс(3) = expires_utc
        cinvoke  printf,<' --> %s',0>,eax

         inc     [counter]  ;// считаем кукисы
         jmp     @b         ;// уходим на повтор..

@free:  cinvoke  printf,<10,10,' ******************************',\
                         10,' Total cookies found: %d',10,0>,[counter]

@exit:  cinvoke  _getch
        cinvoke  exit,0
;//------------
section '.idata' import data readable
library  kernel32,'kernel32.dll',shell32,'shell32.dll',\
         msvcrt,'msvcrt.dll',sqlite3,'sqlite3.dll'

include  'api\kernel32.inc'
include  'api\shell32.inc'
include  'api\sqliteAPI.inc'  ;//<--- импорт API
include  'api\msvcrt.inc'     ;// ^^^^^^^^^^^^^^

Cookies_Log.png


Обратите внимание на время жизни последнего кукиса с достопочтенного сайта wasm.in. Актуальность его заканчивается далеком в прошлом 1601-год (время отсчёта Unix-систем). Это потому, что данный кукис вечный и в его столбце expires_utc лежит значение нуль. По идее, такие ошибки нужно обрабатывать, что было делать мне лень.

На этом ставлю точку.
В скрепке можно будет найти два экзешника, и три инклуда: SqliteAPI, MsvcrtAPI и sqlite3.inc с описанием констант. Всем удачи, пока!
 

Вложения

  • Cookie_List.zip
    8,8 КБ · Просмотры: 324
Последнее редактирование:

Zigun

One Level
09.08.2021
4
1
BIT
1
Marylin, спасибо за очередную интересную серию статей. По первой статье все было норм, в вот тут столкнулся с ошибкой подгрузки sqlite3.dll, скин прикрепил. При этом SQlite Expert Parser x64 работает без проблем, брал оттуда .dll
1648977605910.png
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!