#编程

最近有不少好剧,有时候网速不好追剧太累了,而且有的有广告。看了一下几个主流的视频网站,有不少都还是用的标准的hls协议,没有在此基础上做修改(所以容易导致影视资源泄漏)。用标准hls协议的好处就是我们可以基于hls协议很方便地将影视资源多线程快速下载到本地,既可以流畅观看又可以去广告(部分)。

于是写了一个多线程的m3u8的文件下载器,基于python3纯原生库,安全放心:

代码链接:

https://github.com/Chorder/m3u8_downloader

顺便说一句,m3u8文件挺有意思的,结合ffmepg的缺陷,曾经爆出过播放器任意文件读取漏洞 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-1897 ,但是亲测在浏览器中m3u8文件其实还有更多妙用。感兴趣的童鞋可以进一步玩耍一下。

在CentOS 6 机器中安装sassc Gem,报如下的错误:

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
[root@localhost ~ ]# gem install sassc
Building native extensions. This could take a while...
ERROR: Error installing sassc:
ERROR: Failed to build gem native extension.

current directory: /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/ext
/usr/local/rvm/rubies/ruby-2.6.2/bin/ruby -rrubygems /usr/local/rvm/rubies/ruby-2.6.2/lib/ruby/gems/2.6.0/gems/rake-12.3.2/exe/rake RUBYARCHDIR\=/usr/local/rvm/gems/ruby-2.6.2/extensions/x86_64-linux/2.6.0/sassc-2.0.1 RUBYLIBDIR\=/usr/local/rvm/gems/ruby-2.6.2/extensions/x86_64-linux/2.6.0/sassc-2.0.1
cd libsass
make lib/libsass.so
mkdir lib
cc -Wall -O2 -I /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/ext/libsass/include -fPIC -fPIC -c -o src/cencode.o src/cencode.c
src/cencode.c: In function ‘base64_encode_block’:
src/cencode.c:50: warning: empty declaration
src/cencode.c:64: warning: empty declaration
g++ -Wall -O2 -std=c++0x -I /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/ext/libsass/include -fPIC -fPIC -c -o src/ast.o src/ast.cpp
In file included from src/ast.cpp:2:
src/ast.hpp: In member function ‘virtual size_t Sass::Vectorized<T>::hash()’:
src/ast.hpp:336: error: expected initializer before ‘:’ token
src/ast.hpp:339: error: expected primary-expression before ‘}’ token
src/ast.hpp:339: error: expected ‘;’ before ‘}’ token
src/ast.hpp:339: error: expected primary-expression before ‘}’ token
src/ast.hpp:339: error: expected ‘)’ before ‘}’ token
src/ast.hpp:339: error: expected primary-expression before ‘}’ token
src/ast.hpp:339: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In constructor ‘Sass::Hashed::Hashed(size_t)’:
src/ast.hpp:373: error: ‘class Sass::ExpressionMap’ has no member named ‘reserve’
src/ast.hpp: In member function ‘Sass::Hashed& Sass::Hashed::operator+=(Sass::Hashed*)’:
src/ast.hpp:402: error: expected initializer before ‘:’ token
src/ast.hpp:406: error: could not convert ‘Sass::Hashed::reset_duplicate_key()’ to ‘bool’
src/ast.hpp:407: error: expected primary-expression before ‘return’
src/ast.hpp:407: error: expected ‘)’ before ‘return’
In file included from src/ast.cpp:2:
src/ast.hpp: In member function ‘virtual size_t Sass::Map::hash()’:
src/ast.hpp:1153: error: expected initializer before ‘:’ token
src/ast.hpp:1157: error: expected primary-expression before ‘}’ token
src/ast.hpp:1157: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1157: error: expected primary-expression before ‘}’ token
src/ast.hpp:1157: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1157: error: expected primary-expression before ‘}’ token
src/ast.hpp:1157: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual size_t Sass::Function_Call::hash()’:
src/ast.hpp:1522: error: expected initializer before ‘:’ token
src/ast.hpp:1524: error: expected primary-expression before ‘}’ token
src/ast.hpp:1524: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1524: error: expected primary-expression before ‘}’ token
src/ast.hpp:1524: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1524: error: expected primary-expression before ‘}’ token
src/ast.hpp:1524: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual size_t Sass::Number::hash()’:
src/ast.hpp:1614: error: expected initializer before ‘:’ token
src/ast.hpp:1616: error: expected primary-expression before ‘for’
src/ast.hpp:1616: error: expected ‘;’ before ‘for’
src/ast.hpp:1616: error: expected primary-expression before ‘for’
src/ast.hpp:1616: error: expected ‘)’ before ‘for’
src/ast.hpp:1616: error: expected initializer before ‘:’ token
src/ast.hpp:1618: error: expected primary-expression before ‘}’ token
src/ast.hpp:1618: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1618: error: expected primary-expression before ‘}’ token
src/ast.hpp:1618: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1618: error: expected primary-expression before ‘}’ token
src/ast.hpp:1618: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘bool Sass::String_Schema::has_interpolants()’:
src/ast.hpp:1791: error: expected initializer before ‘:’ token
src/ast.hpp:1794: error: expected primary-expression before ‘return’
src/ast.hpp:1794: error: expected ‘;’ before ‘return’
src/ast.hpp:1794: error: expected primary-expression before ‘return’
src/ast.hpp:1794: error: expected ‘)’ before ‘return’
src/ast.hpp: In member function ‘virtual size_t Sass::String_Schema::hash()’:
src/ast.hpp:1801: error: expected initializer before ‘:’ token
src/ast.hpp:1803: error: expected primary-expression before ‘}’ token
src/ast.hpp:1803: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1803: error: expected primary-expression before ‘}’ token
src/ast.hpp:1803: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1803: error: expected primary-expression before ‘}’ token
src/ast.hpp:1803: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual size_t Sass::Compound_Selector::hash()’:
src/ast.hpp:2750: error: ‘template<class T> class Sass::Vectorized’ used without template parameters
src/ast.hpp: In member function ‘virtual size_t Sass::Selector_List::hash()’:
src/ast.hpp:2997: error: ‘template<class T> class Sass::Vectorized’ used without template parameters
src/ast.hpp: In member function ‘virtual void Sass::Selector_List::set_media_block(Sass::Media_Block*)’:
src/ast.hpp:3014: error: expected initializer before ‘:’ token
src/ast.hpp:3017: error: expected primary-expression before ‘}’ token
src/ast.hpp:3017: error: expected ‘;’ before ‘}’ token
src/ast.hpp:3017: error: expected primary-expression before ‘}’ token
src/ast.hpp:3017: error: expected ‘)’ before ‘}’ token
src/ast.hpp:3017: error: expected primary-expression before ‘}’ token
src/ast.hpp:3017: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual bool Sass::Selector_List::has_placeholder()’:
src/ast.hpp:3019: error: expected initializer before ‘:’ token
src/ast.hpp:3022: error: expected primary-expression before ‘return’
src/ast.hpp:3022: error: expected ‘;’ before ‘return’
src/ast.hpp:3022: error: expected primary-expression before ‘return’
src/ast.hpp:3022: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Selector_List::find(bool (*)(Sass::AST_Node_Obj))’:
src/ast.cpp:35: error: expected initializer before ‘:’ token
src/ast.cpp:39: error: expected primary-expression before ‘return’
src/ast.cpp:39: error: expected ‘;’ before ‘return’
src/ast.cpp:39: error: expected primary-expression before ‘return’
src/ast.cpp:39: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::find(bool (*)(Sass::AST_Node_Obj))’:
src/ast.cpp:45: error: expected initializer before ‘:’ token
src/ast.cpp:49: error: expected primary-expression before ‘return’
src/ast.cpp:49: error: expected ‘;’ before ‘return’
src/ast.cpp:49: error: expected primary-expression before ‘return’
src/ast.cpp:49: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual void Sass::Arguments::set_delayed(bool)’:
src/ast.cpp:98: error: expected initializer before ‘:’ token
src/ast.cpp:102: error: expected primary-expression before ‘}’ token
src/ast.cpp:102: error: expected ‘)’ before ‘}’ token
src/ast.cpp:102: error: expected primary-expression before ‘}’ token
src/ast.cpp:102: error: expected ‘;’ before ‘}’ token
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::has_parent_ref() const’:
src/ast.cpp:171: error: expected initializer before ‘:’ token
src/ast.cpp:174: error: expected primary-expression before ‘return’
src/ast.cpp:174: error: expected ‘;’ before ‘return’
src/ast.cpp:174: error: expected primary-expression before ‘return’
src/ast.cpp:174: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::has_real_parent_ref() const’:
src/ast.cpp:179: error: expected initializer before ‘:’ token
src/ast.cpp:182: error: expected primary-expression before ‘return’
src/ast.cpp:182: error: expected ‘;’ before ‘return’
src/ast.cpp:182: error: expected primary-expression before ‘return’
src/ast.cpp:182: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::is_superselector_of(Sass::Selector_List_Obj, std::string)’:
src/ast.cpp:846: error: expected initializer before ‘:’ token
src/ast.cpp:849: error: expected primary-expression before ‘return’
src/ast.cpp:849: error: expected ‘;’ before ‘return’
src/ast.cpp:849: error: expected primary-expression before ‘return’
src/ast.cpp:849: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘Sass::Selector_List* Sass::Complex_Selector::resolve_parent_refs(std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >&, Sass::Backtraces&, bool)’:
src/ast.cpp:1408: error: expected initializer before ‘:’ token
src/ast.cpp:2226: error: expected primary-expression at end of input
src/ast.cpp:2226: error: expected ‘;’ at end of input
src/ast.cpp:2226: error: expected primary-expression at end of input
src/ast.cpp:2226: error: expected ‘)’ at end of input
src/ast.cpp:2226: error: expected statement at end of input
src/ast.cpp:2226: error: expected ‘}’ at end of input
src/ast.cpp:2226: error: expected ‘}’ at end of input
src/ast.cpp: At global scope:
src/ast.cpp:2226: error: expected ‘}’ at end of input
src/units.hpp:11: warning: ‘Sass::PI’ defined but not used
make: *** [src/ast.o] Error 1
rake aborted!
Command failed with status (2): [make lib/libsass.so...]
/usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/lib/tasks/libsass.rb:31:in `block (2 levels) in <top (required)>'
/usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/lib/tasks/libsass.rb:13:in `block (3 levels) in <top (required)>'
/usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/lib/tasks/libsass.rb:12:in `block (2 levels) in <top (required)>'
Tasks: TOP => lib/libsass.so
(See full trace by running task with --trace)

rake failed, exit code 1

Gem files will remain installed in /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1 for inspection.
Results logged to /usr/local/rvm/gems/ruby-2.6.2/extensions/x86_64-linux/2.6.0/sassc-2.0.1/gem_make.out

经排查,是因为GCC的版本过低导致的。

按照这个步骤,检查下GCC版本,如果是同样的版本和报错,那么可以参考以下的解决方法:

1
2
[root@localhost ~]# gcc --version | head -n1
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)

如果GCC是这个版本,那就安装新版本的的GCC:

1
2
yum install centos-release-scl-rh
yum install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils

安装好以后,再次配置GCC环境并检查版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]# cat << _EOF_ > /etc/profile.d/devtoolset.sh
> #!/bin/bash
> source scl_source enable devtoolset-7
> _EOF_
[root@localhost ~]#
[root@localhost ~]# gcc --version | head -n1
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)
[root@localhost ~]# cat /etc/profile.d/devtoolset.sh
#!/bin/bash
source scl_source enable devtoolset-7
[root@localhost ~]# source /etc/profile.d/devtoolset.sh
[root@localhost ~]# gcc --version | head -n1
gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)

确认GCC配置好以后,再次执行bundle或者执行gem install sassc来安装即可。

Python 3 通过SMTP库发送普通邮件(Through SSL)

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
#!/usr/bin/python3

import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

mail_host = "smtp.chorder.net"
mail_port = 994
mail_user = "[email protected]"
mail_pass = "password"

sender_name = "Example"
sender_account = '[email protected]'
receivers = ['[email protected]']
receiver_name = "Somebody"

subject = 'Mail Subject'
mail_msg = '''
<h1>This is a test main</h1>
<p>Some text</p>
'''


msgRoot = MIMEMultipart('related')
msgRoot['From'] = Header(sender_name, 'utf-8')
msgRoot['To'] = Header(receiver_name, 'utf-8')
msgRoot['Subject'] = Header(subject, 'utf-8')

msgAlternative = MIMEMultipart('alternative')
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))

msgRoot.attach(msgAlternative)

try:
smtpObj = smtplib.SMTP_SSL( mail_host, mail_port )
#smtpObj.ehlo()
#smtpObj.set_debuglevel(1)
smtpObj.login( mail_user, mail_pass )
smtpObj.sendmail(sender_account, receivers, msgRoot.as_string())
print ("邮件发送成功")
except smtplib.SMTPException:
print ("Error: 无法发送邮件")

Python 3 通过SMTP库发送带图片的邮件(Through SSL)

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
#!/usr/bin/python3

import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

mail_host = "smtp.chorder.net"
mail_port = 994
mail_user = "[email protected]"
mail_pass = "password"

sender_name = "Example"
sender_account = '[email protected]'
receivers = ['[email protected]']
receiver_name = "Somebody"


subject = 'Mail Subject'
mail_msg = '''
<h1>This is a test main</h1>
<p>Some text</p>
<h2>Image</h2>
<p><img src="cid:image1"></p>
'''

# add image attachment
fp = open('test.png', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()

msgImage.add_header('Content-ID', '<image1>')

msgRoot = MIMEMultipart('related')

msgRoot['From'] = Header(sender_name, 'utf-8')
msgRoot['To'] = Header(receiver_name, 'utf-8')
msgRoot['Subject'] = Header(subject, 'utf-8')

msgAlternative = MIMEMultipart('alternative')
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))

msgRoot.attach(msgAlternative)
msgRoot.attach(msgImage)

try:
smtpObj = smtplib.SMTP_SSL( mail_host, mail_port )
#smtpObj.ehlo()
#smtpObj.set_debuglevel(1)
smtpObj.login( mail_user, mail_pass )
smtpObj.sendmail(sender_account, receivers, msgRoot.as_string())
print ("邮件发送成功")
except smtplib.SMTPException:
print ("Error: 无法发送邮件")

错误详情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ruby-2.3.3 - #compiling.......................................................................-
Error running '__rvm_make -j4',
showing last 15 lines of /usr/local/rvm/log/1488041042_ruby-2.3.3/make.log
exts.mk:210: recipe for target 'ext/openssl/all' failed
make[1]: *** [ext/openssl/all] Error 2
make[1]: *** Waiting for unfinished jobs....
installing default nkf libraries
compiling objspace_dump.c
linking shared-object json/ext/generator.so
make[2]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3/ext/json/generator'
linking shared-object objspace.so
make[2]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3/ext/objspace'
linking shared-object nkf.so
make[2]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3/ext/nkf'
make[1]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3'
uncommon.mk:203: recipe for target 'build-ext' failed
make: *** [build-ext] Error 2
++ return 2
There has been an error while running make. Halting the installation.

查看/usr/local/rvm/log/1488041042_ruby-2.3.3/make.log发现是openssl版本过老导致的。

解决方案:
第一步:先安装用于rvm的openssl:

1
rvm pkg install openssl

第二步:编译安装ruby,指定openssl目录(我的是/usr/local/rvm/usr/)

1
rvm install ruby-2.3.3 --with-openssl-dir=/usr/local/rvm/usr/

本次的编程环境: CentOS 6.8
Linux centos 2.6.32-573.8.1.el6.x86_64

在内核的源代码中定义了很多进程和进程调度相关的内容。其实Linux内核中所有关于进程的表示全都放在“进程描述符”这个庞大的结构体当中,关于这个结构体的内容和定义,可以在内核的linux/sched.h文件中找到。
现在就来通过编程实现对进程描述符的操作,主要是读取。至于修改等操作,将在后面的内容中提到。
通过对进程描述符的读取,可以获取进程的一切内容,包括进程的ID,进程的地址空间等等。

不多说,上代码:

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
//20160912
//currentptr.c

#include <linux/tty.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/module.h>

/*Function To Write Msg To TTY*/
void tty_write_message(struct tty_struct *tty,char *msg){
if(tty && tty->ops->write){
tty->ops->write(tty,msg,strlen(msg));
}
return;
}

static int my_init(void){
char *msg="Hello tty!\n";
tty_write_message(current->signal->tty,msg);
printk("Hello -- from the kernel...\n");
printk("Parent pid: %d(%s)\n",current->parent->pid,current->parent->comm);
printk("Current pid: %d(%s)\n",current->pid,current->comm);
printk("Current fs: %d\n",current->fs);
printk("Current mm: %d\n",current->mm);
return 0;
}

static void my_cleanup(void){
printk("Goodbye -- from the kernel...\n");
}

module_init(my_init);
module_exit(my_cleanup);

以上的代码,主要就是通过引入内核头文件,进而引用进程描述符中的指针,并通过这种方式获取当前进程和相关进程的描述信息。
Makefile文件如下:

1
2
#Makefile
obj-m += currentptr.o

编译的指令:

1
make -C /usr/src/linux SUBDIRS=$PWD modules

然后通过insmod把模块装载进内核,首先tty输出了Hello tty!
同时在/var/log/message中,模块打印出了这些内容:

1
2
3
4
5
Sep 12 10:35:36 centos kernel: Hello -- from the kernel...
Sep 12 10:35:36 centos kernel: Parent pid: 2235(bash)
Sep 12 10:35:36 centos kernel: Current pid: 13197(insmod)
Sep 12 10:35:36 centos kernel: Current fs: 927961856
Sep 12 10:35:36 centos kernel: Current mm: 932613056

分别是这个进程的相关信息。
对于进程描述符的定义,在本次实验用来编译的内核源码包(kernel-devel-2.6.32-642.4.2.el6.x86_64)中,
进程描述符具体定义在include/linux/sched.h的1326行往后。

需要参考的进程具体信息都在其中,可随时参考,以备不时之需。

Linux内核编程一直是我很想掌握的一个技能。如果问我为什么,我也说不上来。
也许是希望有一天自己的ID也出现在内核开发组的邮件列表里?或是内核发行文件的CREDITS文件上?
也许是吧。其实更多的,可能是对于底层的崇拜,以及对于内核的求索精神。
想到操作系统的繁杂,想到软件系统之间的衔接,内心觉得精妙的同时,更是深深的迷恋。
所以从这篇文章开始,我要真正的走进Linux内核里了,让代码指引我,去奇妙的世界一探究竟。

在这篇文章中,一起来对内核说Hello World。
本次的编程环境:
CentOS 6.8

Linux centos 2.6.32-573.8.1.el6.x86_64

没有安装内核的,可能需要安装一下内核源码包
kernel-devel-2.6.32-642.4.2.el6.x86_64

1
yum install kernel-devel-2.6.32-642.4.2.el6.x86_64

安装好之后,这个版本内核可以在/usr/src/linux找到。

然后先话不多说,首先看代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//20160904
//kernel_hello_world.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int __init lkp_init(void){
printk("Hello,World! --from the kernel space...\n");
return 0;
}

static void __exit lkp_cleanup(void){
printk("Goodbye,World! --leaving kernel space...");
}

module_init(lkp_init);
module_exit(lkp_cleanup);

以上代码是kernel_hello_world.c内容。
作为内核模块,在编译的时候,Makefile文件这样写:

1
2
#File:Makefile
obj-m += kernel_hello_world.o

然后可以通过这条命令来编译:

1
make -C /usr/src/linux SUBDIRS=$PWD modules

编译好以后,目录下面的文件可能是这样子:

1
2
3
kernel_hello_world.ko.unsigned  kernel_hello_world.o  Module.symvers
kernel_hello_world.c kernel_hello_world.mod.c Makefile
kernel_hello_world.ko kernel_hello_world.mod.o modules.order

有这么多文件被生成,其中kernel_hello_world.ko就是本次编译出来的内核模块文件,在Linux内核中有很多这样的模块,它们可能充当着不同的角色,可能是驱动,也可能是各种设备。
这个模块会在/var/log/message文件中打印一行字,即Hello,World! --from the kernel space...
可以使用insmod kernel_hello_world.ko来将这个模块载入到内核。
使用lsmod来查看是否已经加载。
使用rmmod kernel_hello_world.ko来卸载这个模块。
可以tail /var/log/message来看一下是否成功执行了呢?

Hello,Kernel.

VmWare默认的镜像格式是.vmdk格式的,VirtualBox则默认是.vdi格式的。其实这在VirtualBox新建虚拟机的过程中是可选的。

导入.vmdk格式的镜像到VirtualBox只需要新建一个虚拟机,并且不创建虚拟硬盘。如下图:

无视警告,继续:

创建好之后,在设置里面把.vmdk格式的虚拟硬盘添加进去:

这样就可以了。

如果遇到windows虚拟机起不开的情况,尝试更改下下面这个选项:
启用下I/O APIC试试。

最近在研究二进制,研究到函数调用部分,将自己理解的原理做个记录。

首先需要了解系统栈的工作原理,栈可以理解成一种先进后出的数据结构,这就不用多说了。
在操作系统中,系统栈也起到用来维护函数调用、参数传递等关系的一个作用。嗯,这是我的理解。
在高级语言编程中,函数调用的底层原理是对用户屏蔽的,所以不用过多的纠结于底层的实现。而对于
汇编研究者来说,了解这个原理就很重要了。
首先可以想象一下,汇编语言在内存中是以指令的形式存在的,这些指令是按照顺序存储和执行的,高级语言中
编写的循环、调用,到了底层都会变成一些最基本的判断和跳转,如何在线性的结构上完成“非线性”的过程调度,
理解了这些,就理解了汇编。

这里先抛出高级语言的一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
/*20160701*/
#include <stdio.h>

int funcA( int arg ){
arg += 1;
return arg;
}

int main(){
int a;
a = funcA(1);
printf("%d", a);
}

在这个程序中,main函数调用了函数funcA,funcA对传入的数据进行+1然后返回。
这个程序在编译之后,main函数变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400516 <+0>: push rbp
0x0000000000400517 <+1>: mov rbp,rsp
0x000000000040051a <+4>: sub rsp,0x10
0x000000000040051e <+8>: mov edi,0x1
0x0000000000400523 <+13>:call 0x400506 <funcA>
0x0000000000400528 <+18>:mov DWORD PTR [rbp-0x4],eax
0x000000000040052b <+21>:mov eax,DWORD PTR [rbp-0x4]
0x000000000040052e <+24>:mov esi,eax
0x0000000000400530 <+26>:mov edi,0x4005d4
0x0000000000400535 <+31>:mov eax,0x0
0x000000000040053a <+36>:call 0x4003e0 <printf@plt>
0x000000000040053f <+41>:leave
0x0000000000400540 <+42>:ret
End of assembler dump.

其中rbp是调用main函数的函数的栈桢的底部,这么说有点绕,简单的来说,main函数调用了funcA,那funcA中首先要做的一件事情就是把调用它的main函数栈桢的底部保存,所以在main函数被操作系统装载执行之后,main要做的首先是把调用它的函数的栈桢的底部保存,不然怎么返回呢?
第二个步骤把rsp的值传递给rbp,这是替换当前栈桢的底部,因为调用了funcA,所以要为funcA创建独立的栈桢,于是抬高栈底,怎么抬高呢,把栈顶传给指向栈桢底部的指针就可以了。
下一步是抬高栈顶,这是为funcA创建栈桢空间。
接着将参数传递给edi,因为这里只有一个参数,所以不涉及到参数顺序的问题,关于这个问题,可以去了解一下函数调用约定
调用了funcA,再来观察一下funcA的内部机制:

1
2
3
4
5
6
7
8
9
10
(gdb) disassemble funcA
Dump of assembler code for function funcA:
0x0000000000400506 <+0>: push rbp
0x0000000000400507 <+1>: mov rbp,rsp
0x000000000040050a <+4>: mov DWORD PTR [rbp-0x4],edi
0x000000000040050d <+7>: add DWORD PTR [rbp-0x4],0x1
0x0000000000400511 <+11>: mov eax,DWORD PTR [rbp-0x4]
0x0000000000400514 <+14>: pop rbp
0x0000000000400515 <+15>: ret
End of assembler dump.

同样的,在funcA中,首先保存上一个函数,即main函数栈桢的栈底,然后将rsp的值赋给rbp,抬高栈桢底部。
接着从edi中取得参数,并放入位于自身栈桢空间中,rbp之后的双字单元内。
然后执行操作,将其自增。
执行完成之后,将返回值保存在eax中,等待返回。
弹出上一个函数的栈桢的底部,重新回到main函数的空间。

PS:
直到目前为止,这个程序反编译出来的结果和书上说的原理还是有一些出入的,还有下面几个问题:
0x01 书上说的是,传递参数,会将参数按照一定顺序压栈,而不是像本程序中这样使用edi
0x02 在main函数调用funcA函数之后,将栈顶指针esp抬高了,但是在funcA函数执行完成需要返回到main函数的时候,只恢复了ebp指针,并没有恢复esp指针,这是为什么?

希望接下来可以搞懂上面的两个问题。
本文中用到的相关代码和程序下载:

1037666925.zip

环境:
Windows 10
Python 2.7.10

0x01 安装PyQt4
在这个页面下载,注意选对版本。
https://riverbankcomputing.com/software/pyqt/download
我选择的版本是 PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x64.exe

0x02 编写测试脚本

1
2
3
4
5
6
7
8
9
import sys
from PyQt4 import QtGui

app = QtGui.QApplication(sys.argv)
widget = QtGui.QWidget()
widget.resize(250, 150)
widget.setWindowTitle('PyQt')
widget.show()
sys.exit(app.exec_())

如果成功运行并弹出一个空白的窗口,说明PyQt4已经安装上了。

0x03 使用PyQt4的QtWebKit实现解析Dom

待续。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×