一个进程的意义,或在于,它有它要执行的任务。
有的为了调度,有的为了计算,有的为了IO,有的为了传输。
一个进程的意义,或在于,它要为后续的进程创造条件。
在时空里埋下线索,为后续的crash保留好进程上下文。Debug的过程或许痛苦,但是螺旋式上升(或者下沉)必须经历。
一个进程的意义,或在于,它要代表一颗星星,静静地挂在内存的夜空。
一个进程的意义,或在于,它有它要执行的任务。
有的为了调度,有的为了计算,有的为了IO,有的为了传输。
一个进程的意义,或在于,它要为后续的进程创造条件。
在时空里埋下线索,为后续的crash保留好进程上下文。Debug的过程或许痛苦,但是螺旋式上升(或者下沉)必须经历。
一个进程的意义,或在于,它要代表一颗星星,静静地挂在内存的夜空。
链接通俗来说就是C语言程序在编译过程中,编译器将所有的资源“拼接”到二进制文件中,从而形成最终的可执行文件的过程。
链接库文件通常就是一些专门存放一些通用函数的文件,动态和静态库的区别就在于,动态库是随着程序的发布一起发布的,作为独立的模块发布。
程序需要用到其中的函数时,动态地加载这些模块,从而调用其中的功能。
而静态库则是程序在编译的时候,从库中将所需要用到的函数、类等提取出来,复制到自身的可执行文件中。
在Linux中,静态链接库文件的后缀名通常是.a
;在Windows系统中,静态链接库文件的后缀名为.lib
。
在Linux中,动态链接库文件的后缀名通常是.so
;在Windows系统中,动态链接库文件的后缀名为.dll
。
一个简单的Linux动态链接创建实例:
源文件:func1.c和func2.c编译生成testlib.so,testlib.h中声明了testlib.so的函数,main.c调用testlib.so中的函数。
func1.c:
1 | #include "testlib.h" |
func2.c:
1 | #include "testlib.h" |
testlib.h:
1 | #ifndef __TEST_H_ |
编译:
编译生成testlib.so
:
1 | gcc -fpic -shared func1.c func2.c -o testlib.so |
Linux动态链接库的隐式调用,就是将生成的so文件直接放到系统的Lib路径中,可执行程序在执行调用之前系统会自动将库文件加载到内存中,而不需要手动去加载。
main.c:
1 | #include <stdio.h> |
编译生成main:
1 | gcc main.c testlib.so -o main |
生成之后如果直接执行main会报错:
1 | ./main: error while loading shared libraries: testlib.so: cannot open shared object file: No such file or directory |
因为此时系统不知道应该从哪里加载testlib.so:
1 | chorder@debian:~/testlib$ldd main |
只需要将testlib.so
拷贝到/usr/lib/
即可:
1 | chorder@debian:~/testlib$sudo cp testlib.so /usr/lib/ |
main_d.c:
1 | #include <dlfcn.h> |
编译生成main_d:
1 | gcc main_d.c -ldl -o main_d |
可以直接运行main_d:
1 | chorder@debian:~/testlib$gcc main_d.c -ldl -o main_d |
静态链接相对来说比较简单,只需要在编译的时候加上相应的参数即可将函数编译到可执行文件中。
一个简单的Linux下的静态链接库的例子:
add.c和sub.c编译生成libtest.a,libtest.h中声明了相应的函数,main.c调用libtest.a中的函数。
add.c
1 | int add(int a, int b){ |
sub.c
1 | int sub(int a, int b){ |
libtest.h
1 | #ifndef __TEST_H_ |
main.c
1 | #include <stdio.h> |
编译:
编译add.c和sub.c,生成目标文件 add.o sub.o
1 | gcc -c add.c sub.c |
归档目标文件,生成静态链接库 libtest.a
使用 ar 命令将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和检索
1 | ar rcv libtest.a add.o sub.o |
编译main.c:
1 | gcc main.c -L. -ltest -o main |
Windows的动态链接库一般是DLL,这里创建一个DLL工程,func1.c和func2.c组合编译成testlib_win.dll,并通过两种方法分别调用testlib_win.dll中的函数。
第一种称之为显式链接,只需提供DLL文件和知晓函数名即可;第二种称之为隐式链接,需要提供lib,头文件和dll。
首先在VS2019中创建DLL项目:
func1.c:
1 | #include "testlib_win.h" |
func2.c:
1 | #include "testlib_win.h" |
testlib_win.h
1 | #ifndef __TEST_H_ |
直接编译会报错,需要修改一下项目属性,不使用预编译头:
点击生成解决方案,即可编译出DLL:
此时生成的文件中只有dll,并没有lib文件,如果想要生成lib文件,则需要对testlib_win.h文件进行修改:
testlib_win.h
1 | #ifndef __TEST_H_ |
此时编译出的文件中,就包含了testlib_win.lib:
创建工程,包含testlib_win.h头文件,在其中加载DLL并调用add和sub函数:
main.c
1 | #include <Windows.h> |
将testlib_win.h加入到源码目录,将testlib_win.dll加入到编译输出的文件所在目录:
运行即可:
由于不常用,以后再补充。
由于不常用,以后再补充。
(待续)
GCC使用静态链接库和动态链接库
C/C++动态链接库的显式调用(动态调用)
linux静态链接库
什么是 DLL
windows LoadLibrary使用示例
Visual Studio 2013中.dll文件的显式调用方法
Windows DLL调用实例
VS2017生成一个简单的DLL文件 和 LIB文件——C语言
今年27了,终于明白副业是个伪命题。
从我大三实习那年起,在维持主业的同时,我就一直热衷于探索副业。
最开始在淘宝上卖乐器,在58同城倒腾二手物品,后来尝试做CPA、淘宝客、建站做Adsense,以及出教程、搞培训,炒股、炒币、买基金…
除了炒股以外,别的基本上没亏过钱。但也没有因此赚过什么钱。
过去的我,太急于开辟一条新的赛道了,以至于在主业(指网络安全)的道路上还没有做出什么成绩,就想着赶紧脱离这一条一眼忘不到头的技术路。
幻想着能够有朝一日把副业从小做大,慢慢扶正,让主业真正成为一个爱好。
然而幻想终究是一种幻想,相信许多人都会有这种幻想。
这种幻想太幼稚了。如今我终于认识到,以大部分人的天资,能够在主业的道路上有所建树,已经是莫大的成功了。
更何况我们这些搞安全的技术小子,如今能凭借这一身牢底坐穿的手艺有口饭吃,绝对要感谢老天爷。
要好好珍惜主业的机会,踏踏实实继续突破。
以后不谈副业了。
Windows系统下C语言中使用自定义包的方法:
首先明确GOPATH的路径,执行go env | findstr GOPATH
1 | C:\Users\CHORDER>go env | findstr GOPATH |
接着在GOPATH
目录中创建相应的自定义包,这里定义一个example
包,并创建两个源码文件src1.go
和src2.go
,源码内容如下:
1 | /* C:\Users\CHORDER\go\src\chorder.net\example\src1.go */ |
1 | /*C:\Users\CHORDER\go\src\chorder.net\example\src2.go*/ |
编写代码调用这两个包中的方法:
packge_test.go
1 | package main |
执行结果:
1 | >go run packge_test.go |
在典型的IPv4网络下,由于NAT技术的广泛使用,端口映射是一种刚需。(下文所涉及“端口转发”、“端口映射”均指同一种技术。)
经典的端口映射方法例如iptables端口转发、SSH端口转发、webshell流量转发(regeorg)、socks代理等技术,是比较常见的用于建立内网通道的技术。本文分享一种利用内网网关设备开放的upnp协议进行端口映射的方法。
关于upnp协议的解释,参考百度百科-UPNP
upnp协议的使用场景很多,端口转发是upnp其中一个功能,但是想要使用该功能,需要网关设备的支持。
使用upnp进行端口转发的场景,以下图网络拓扑为例:
内网服务器Server:内网地址192.168.1.2,开放端口1234
网关设备Gateway:内网地址192.168.1.1,公网地址x.x.x.x
常规情况下,如果需要通过公网地址x.x.x.x访问192.168.1.2中的开放端口1234,则可以在Gateway中配置端口转发,但此时至少要有192.168.1.1的(部分)权限。
如果Gateway具备unpn功能,并且启用了unpn服务,则可以在Gateway外部通过upnp指令,打开Gateway上的转发通道,从而完成端口转发。
Gateway开启upnp示例(一般位于路由等设备的配置界面中):
Metasplioit中有upnp相关的插件,但是不太好用,姿势问题?
插件是:
可以自行探索之
miranda-upnp是之前在Github上找到的一个工具,基于python2编写,可以用于内网upnp端口转发通道的建立。
也可以根据upnp协议自行实现相关工具,协议使用可以参考这篇文章
以第2节中的拓扑为例,在内网IP为192.168.1.2的Server中运行miranda-upnp,打开转发通道,在Gateway的x.x.x.x:1234与Server 192.168.1.2:1234之间建立映射。
运行miranda-upnp后,首先执行msearch
:
1 | upnp> msearch |
此时已经获得Gateway中的SSDP描述文件,Ctrl-C停止SSDP搜寻。
执行host list
,列出扫描到的主机,并执行host get 0
选中主机0(Gateway):
1 | upnp> host list |
执行deviceList
和services
命令分别查看设备列表和设备中的服务:
1 | upnp> host info 0 deviceList InternetGatewayDevice services |
常规的端口转发功能我们要使用的是WANConnectionDevice
设备的WANIPConnection
服务,执行actions
查看其动作,这里可以看到存在一个名为AddPortMapping
的action,我们只要调用这个action,并填写相应参数,即可完成端口转发。
1 | upnp> host info 0 deviceList WANConnectionDevice services WANIPConnection actions |
可以看到此时Gateway中已经激活了相应的转发通道:
在Windows中创建服务一般需要先编写服务程序的代码,然后使用SCM注册这个服务。
手动注册一个Windows服务的方法是:
1 | # 注册服务 |
这里实现了一个最基本的Windows服务程序,服务启动之后监听本地TCP 8888端口,接收和发送数据。
1 | /*service.cpp*/ |
1 | /*server.cpp*/ |
1 | /*utils.cpp*/ |
1 | /*service.h*/ |
开发 Windows 服务应用
C语言开发Windows服务
C++编写Windows服务
C++编写Windows服务
Windows 服务程序(一)
Windows 服务程序(二)
windows环境下C语言socket编程
因为很多私事,复习停滞了两个半月,真是太惭愧了。不说了,菜鸡抽空继续学。
Service是一种被称为守护进程(daemon)的程序。它通常一旦启动后就在后台持续运行,通常在等待什么输入或者监控系统有什么变化。例如Apache服务器有一个叫httpd的守护进程监听80端口以等待http请求。
Service程序通常通过service命令来启动或停止等。例如apache服务的启动可通过
service httpd start
来启动。通过
service --status-all
可以查看系统当前所有service服务的状态。
通过以下样例程序,结合前期复习的socket相关知识,以及最基本的Linux系统调用,实现了一个运行在Linux中的服务程序(Daemon)。
这个程序会在后台监听当前主机的4444端口,当tcp客户端连接上时,会接受客户端的输入,并作为shell来执行,实现最基本的C/S架构的BD功能。
(后面也将继续基于这个例子进一步改良和优化这个程序。)
1 | /* |
Linux平台下的service程序编写指南
Linux中创建Daemon进程的三种方法
守护进程详解及创建,daemon使用
DNS
利用C语言实现DNS查询和DNS响应包的解析。
1 | /* |
HTTP
利用C语言实现HTTP请求,可以采用原生Socket往端口发包,根据HTTP协议自行构造请求的方式。
但更方便的方式是使用libcurl库。自行构造Socket请求的方式既不能保证性能,又无法保证安全。
libcurl库至少是相对完善的第三方库。
详细用法,参考libcurl官方文档以及libcurl官方样例。
SMTP
SMTP一例
1 | /* |
其他协议,后续学到再补充。
在前一夜的复习中实现了一个C/S架构的TCP套接字demo。今天首先通过创建一个UDP的套接字例子来区分UDP Socket和TCP Socket的使用区别。
客户端:
1 | /* |
服务端:
1 | /* |
本例以一个简单的http server来演示socket server构建:
1 | /* |
在阻塞的套接字中,服务端接收到的请求需要排队对其进行处理,这就形成了套接字阻塞。为了解决套接字阻塞的问题,可以创建非阻塞的服务端模型。
一个在网上找的非阻塞套接字的例子:
1 | /*************************************************************************** |
待后续补充。
Linux socket 编程,第一部分
Linux socket 编程,第二部分
Linux下的socket演示程序
编写一个单进程非阻塞多客户的套接字客户端
Update your browser to view this website correctly. Update my browser now