├── .gitignore
├── .idea
├── .gitignore
├── dictionaries
│ └── gaba.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── why.iml
├── GoHack.pdf
├── README.md
├── bin
├── agent
│ └── agent.go
├── packer
│ └── packer.go
└── web
│ └── web.go
├── build.sh
├── frontend
├── alertlist.html
└── applist.html
├── go.mod
├── lkm
├── Makefile
├── README.md
├── share_mem.c
├── share_mem.h
├── smith_hook.c
├── smith_hook.h
└── struct_wrap.h
├── pkg
├── agent
│ ├── fsnotify.go
│ ├── loadder.go
│ └── loadder_test.go
├── app
│ ├── app.go
│ └── app_test.go
├── client
│ ├── appinfo_test.go
│ └── client.go
├── common
│ └── until.go
├── crypto
│ ├── crypto.go
│ └── crypto_test.go
├── elf
│ ├── elf.go
│ └── elf_test.go
├── integrity
│ ├── hash.go
│ └── validation.go
├── storage
│ ├── alert.go
│ ├── app.go
│ ├── build.go
│ ├── crypto.go
│ ├── storage.go
│ └── storage_test.go
└── web
│ ├── alert.go
│ ├── app.go
│ ├── build.go
│ ├── key.go
│ └── web.go
└── test
├── alert_new.json
└── app_new.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Go template
3 | # Binaries for programs and plugins
4 | *.exe
5 | *.exe~
6 | *.dll
7 | *.so
8 | *.dylib
9 |
10 | # Test binary, built with `go test -c`
11 | *.test
12 |
13 | # Output of the go coverage tool, specifically when used with LiteIDE
14 | *.out
15 |
16 | # Dependency directories (remove the comment below to include it)
17 | # vendor/
18 |
19 | go.sum
20 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /workspace.xml
--------------------------------------------------------------------------------
/.idea/dictionaries/gaba.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | appid
5 | execuable
6 | jsonize
7 | priv
8 | sqlite
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/why.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/GoHack.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlkenePan/KAP/b1a08ef307fd514a77327f2dbc257f553044408c/GoHack.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # KAP
2 |
3 | > @GoHack 2019
4 |
5 | # PPT: [GoHack.pdf](./GoHack.pdf)
6 |
7 | ## desc
8 | * 在构建阶段对可执行文件进行重新打包
9 | * 在执行前经过安全检查和安全加载
10 | * 主要可以防止以下安全问题:
11 | 1. 服务器/二进制文件被重新打包窃密
12 | 2. 二进制文件在非可靠生产环境运行
13 | 3. 反调试
14 | 4. 控制可执行用户权限
15 | 5. 监控可执行文件被更改
16 |
17 | ## build
18 |
19 | ```
20 | go mod download
21 | bash build.sh
22 | ```
23 |
24 | ## run
25 | * web
26 | ```
27 | ./bin/web/web
28 | ```
29 |
30 | * packer
31 | ```
32 | ./bin/packer/packer :5000
33 | ```
34 |
35 | * agent
36 | ```
37 | ./bin/agent -path -host :5000
38 | ```
39 |
40 | ## use flow
41 |
42 | 1. reg new appid
43 |
44 | ```
45 | http POST :5000/app/new < test/app_new.json
46 | ```
47 |
48 | 2. pack
49 |
50 | 3. agent load encrypted file
51 |
52 | 4. (FOR InfoSec&OP) check security alert
53 |
--------------------------------------------------------------------------------
/bin/agent/agent.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "strings"
7 | "youzoo/why/pkg/agent"
8 | "youzoo/why/pkg/app"
9 | "youzoo/why/pkg/client"
10 | "youzoo/why/pkg/common"
11 | "youzoo/why/pkg/elf"
12 | "youzoo/why/pkg/storage"
13 | )
14 |
15 | func getMsgFromFileWatcher(appid string, host string, msgChan chan agent.FileWatcherMsg) {
16 | for i := range msgChan {
17 | alert_data := storage.AlertTable{
18 | Appid: appid,
19 | Level: i.Level,
20 | Type: "file watcher",
21 | Info: i.Msg,
22 | PostContact: "",
23 | }
24 |
25 | err := client.NewAlert(host, appid, &alert_data)
26 | if err != nil {
27 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
28 | }
29 | }
30 | }
31 |
32 | func main() {
33 | var path string
34 | var host string
35 | var argv []string
36 | var cryptoTable storage.CryptoTable
37 |
38 | flag.StringVar(&path, "path", "", "ELF Path")
39 | flag.StringVar(&host, "host", "", "Verify Server Host")
40 |
41 | flag.Parse()
42 |
43 | if path == "" {
44 | fmt.Println(common.RedBg, "[!] ERROR: ELF Path is Null", common.Reset)
45 | return
46 | }
47 |
48 | if host == "" {
49 | fmt.Println(common.RedBg, "[!] ERROR: Verify Server Host is Null", common.Reset)
50 | return
51 | }
52 |
53 | appid, hash := elf.LoadEncryptedFileHeader(path)
54 | err := client.FetchPriKey(host, appid, &cryptoTable)
55 | if err != nil {
56 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
57 | return
58 | }
59 |
60 | _, _, ori_elf_data, err := elf.LoadEncryptedFile(path, []byte(cryptoTable.PriKey))
61 | if err != nil {
62 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
63 | return
64 | }
65 |
66 | file_current_md5 := common.GetBytesMD5(ori_elf_data)
67 |
68 | tempChunk := elf.Chunk{hash, true}
69 | decryptChunk := elf.DecryptChunk(tempChunk, []byte(cryptoTable.PriKey))
70 | if string(decryptChunk.Data) != file_current_md5 {
71 | fmt.Println(common.RedBg, "[!] ERROR: ELF File MD5 Verify Error", common.Reset)
72 | return
73 | }
74 |
75 | appinfo := app.App{}
76 | err = client.FetchAppInfo(host, appid, &appinfo)
77 | if err != nil {
78 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
79 | return
80 | }
81 |
82 | if appinfo.DNS != "" {
83 | if appinfo.DNS != common.GetDNSServer() {
84 | fmt.Println(common.RedBg, "[!] ERROR: DNS Server Error", common.Reset)
85 | return
86 | }
87 | }
88 |
89 | if appinfo.ExecInfo.Argv != "" {
90 | argv = strings.Split(appinfo.ExecInfo.Argv, ";")
91 | }
92 | envv := strings.Split(appinfo.ExecInfo.Envv, ";")
93 |
94 | process, err := agent.ExecveMemfdFromBytes(path, ori_elf_data, appinfo.ExecInfo.UserName, appinfo.ExecInfo.Ptrace, argv, envv)
95 |
96 | if err != nil {
97 | if process != nil {
98 | _ = process.Kill()
99 | }
100 |
101 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
102 |
103 | alert_data := storage.AlertTable{
104 | Appid: appid,
105 | Level: "danger",
106 | Type: "runtime",
107 | Info: err.Error(),
108 | PostContact: "",
109 | }
110 |
111 | err = client.NewAlert(host, appid, &alert_data)
112 | if err != nil {
113 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
114 | }
115 |
116 | return
117 | }
118 |
119 | alert_data := storage.AlertTable{
120 | Appid: appid,
121 | Level: "success",
122 | Type: "runtime",
123 | Info: "",
124 | PostContact: "",
125 | }
126 |
127 | err = client.NewAlert(host, appid, &alert_data)
128 | if err != nil {
129 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
130 | }
131 |
132 | filrWatcherMsgChan := agent.GetNewFileWatcherMsgChan()
133 | go agent.AddNewWatcher(path, filrWatcherMsgChan)
134 | go getMsgFromFileWatcher(appid, host, filrWatcherMsgChan)
135 |
136 | _, err = process.Wait()
137 |
138 | if err != nil {
139 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
140 |
141 | alert_data := storage.AlertTable{
142 | Appid: appid,
143 | Level: "danger",
144 | Type: "runtime(wait)",
145 | Info: err.Error(),
146 | PostContact: "",
147 | }
148 |
149 | err = client.NewAlert(host, appid, &alert_data)
150 | if err != nil {
151 | fmt.Println(common.RedBg, "[!] ERROR: "+err.Error(), common.Reset)
152 | }
153 |
154 | return
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/bin/packer/packer.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "youzoo/why/pkg/client"
6 | "youzoo/why/pkg/common"
7 | "youzoo/why/pkg/elf"
8 | "youzoo/why/pkg/storage"
9 | )
10 |
11 | func main() {
12 | if len(os.Args) <= 1 {
13 | os.Exit(1)
14 | }
15 | host := os.Args[1]
16 | appid := os.Args[2]
17 | src := os.Args[3]
18 | dst := os.Args[4]
19 | if host == "" || appid == "" || src == "" || dst == "" {
20 | os.Exit(1)
21 | }
22 | common.Info("AppId: " + appid)
23 | common.Info("reading file: " + src)
24 | chunks, extraChunk := elf.SplitELF(src)
25 | md5, _ := common.GetFileMD5(src)
26 | headerChunks := elf.HeaderChunks([]byte(appid), []byte(md5))
27 | var cryptoTable storage.CryptoTable
28 | common.Info("Connecting: " + host)
29 | _ = client.FetchPubKey(host, appid, &cryptoTable)
30 | fullChunks := append(headerChunks, chunks...)
31 | fullChunks = append(fullChunks, extraChunk)
32 | encryptChunks := elf.EncryptChunks(fullChunks, []byte(cryptoTable.PubKey))
33 | common.Info("Encrypt Done")
34 | elf.WriteChunk(dst, encryptChunks)
35 | common.Info("Out: " + dst)
36 | }
37 |
--------------------------------------------------------------------------------
/bin/web/web.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "youzoo/why/pkg/web"
4 |
5 | func main() {
6 |
7 | web.StartApi(":5000")
8 | }
9 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | cd bin/web
2 | go build web.go
3 | cd ../packer
4 | go build packer.go
5 | cd ../agent
6 | go build agent.go
7 | cd ..
8 | cd ..
9 |
--------------------------------------------------------------------------------
/frontend/alertlist.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Alert List
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Alert List
14 |
15 |
16 | ID |
17 | CreatedAt |
18 | UpdatedAt |
19 | Appid |
20 | Level |
21 | Type |
22 | Info |
23 | PostContact |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
61 |
--------------------------------------------------------------------------------
/frontend/applist.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AppList
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Alert List
14 |
15 |
16 | Appid |
17 | DNS |
18 | AbsPath |
19 | Argv |
20 | Envv |
21 | Ptrace |
22 | UserName |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
59 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module youzoo/why
2 |
3 | go 1.13
4 |
5 | require (
6 | github.com/ajg/form v1.5.1 // indirect
7 | github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect
8 | github.com/fsnotify/fsnotify v1.4.7
9 | github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424 // indirect
10 | github.com/google/go-querystring v1.0.0 // indirect
11 | github.com/google/uuid v1.1.1
12 | github.com/gorilla/schema v1.1.0 // indirect
13 | github.com/imkira/go-interpol v1.1.0 // indirect
14 | github.com/iris-contrib/formBinder v5.0.0+incompatible // indirect
15 | github.com/iris-contrib/httpexpect v0.0.0-20180314041918-ebe99fcebbce // indirect
16 | github.com/iris-contrib/middleware/cors v0.0.0-20191111233249-6e1f5f92190e
17 | github.com/jinzhu/gorm v1.9.11
18 | github.com/json-iterator/go v1.1.8 // indirect
19 | github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
20 | github.com/kataras/iris v11.1.1+incompatible
21 | github.com/kataras/iris/v12 v12.0.1
22 | github.com/klauspost/compress v1.9.2 // indirect
23 | github.com/mattn/go-colorable v0.1.4 // indirect
24 | github.com/moul/http2curl v1.0.0 // indirect
25 | github.com/sergi/go-diff v1.0.0 // indirect
26 | github.com/smartystreets/goconvey v1.6.4 // indirect
27 | github.com/valyala/fasthttp v1.6.0 // indirect
28 | github.com/xeipuuv/gojsonschema v1.2.0 // indirect
29 | github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
30 | github.com/yudai/gojsondiff v1.0.0 // indirect
31 | github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
32 | github.com/yudai/pp v2.0.1+incompatible // indirect
33 | )
34 |
--------------------------------------------------------------------------------
/lkm/Makefile:
--------------------------------------------------------------------------------
1 | obj-m += smith.o
2 | smith-objs := smith_hook.o share_mem.o
3 |
4 | KERNEL_VER := $(shell uname -r)
5 | KERNEL_DIR := /lib/modules/$(KERNEL_VER)/build
6 | PWD := $(shell pwd)
7 |
8 | all:
9 | $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
10 |
11 | clean:
12 | $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
13 |
14 | insmod:
15 | sudo insmod smith_hook.ko
16 |
17 | rmmod:
18 | sudo rmmod smith_hook
--------------------------------------------------------------------------------
/lkm/README.md:
--------------------------------------------------------------------------------
1 | * `make`
2 | * `instal smith.ko`
3 | * `echo "+/NeedProtedPid/" > /dev/smith`
4 | * `echo "+/NeedCancelProtedPid/" > /dev/smith`
5 | * uninstall: `rmmod smith`
6 |
7 |
--------------------------------------------------------------------------------
/lkm/share_mem.c:
--------------------------------------------------------------------------------
1 | #include "share_mem.h"
2 |
3 | static DEFINE_MUTEX(mchar_mutex);
4 | static struct class *class;
5 | static struct device *device;
6 | static int major;
7 | static char *sh_mem = NULL;
8 | static rwlock_t _write_index_lock;
9 |
10 | static void lock_init(void);
11 | static inline void write_index_lock(void);
12 | static inline void write_index_unlock(void);
13 | static int device_mmap(struct file *filp, struct vm_area_struct *vma);
14 | static ssize_t device_write(struct file *file,const char __user * buffer, size_t length, loff_t * offsetf);
15 |
16 | static const struct file_operations mchar_fops = {
17 | .owner = THIS_MODULE,
18 | .mmap = device_mmap,
19 | .write = device_write,
20 | };
21 |
22 | typedef struct protect {
23 | char *path;
24 | struct list_head list;
25 | } node;
26 |
27 | struct protect *pprotect;
28 | struct list_head protect_list;
29 |
30 | #if DELAY_TEST == 1
31 | static char *get_timespec(void)
32 | {
33 | char *res = NULL;
34 | struct timespec tmp_time;
35 | res = kzalloc(64, GFP_ATOMIC);
36 | tmp_time = current_kernel_time();
37 | snprintf(res, 64, "%lu.%lu", tmp_time.tv_sec, tmp_time.tv_nsec);
38 | return res;
39 | }
40 | #endif
41 |
42 | static void lock_init(void)
43 | {
44 | rwlock_init(&_write_index_lock);
45 | }
46 |
47 | static inline void write_index_lock(void)
48 | {
49 | write_lock(&_write_index_lock);
50 | }
51 |
52 | static inline void write_index_unlock(void)
53 | {
54 | write_unlock(&_write_index_lock);
55 | }
56 |
57 | static inline void read_index_lock(void)
58 | {
59 | read_lock(&_write_index_lock);
60 | }
61 |
62 | static inline void read_index_unlock(void)
63 | {
64 | read_unlock(&_write_index_lock);
65 | }
66 |
67 | void del_protect_list(char *path)
68 | {
69 | node *s;
70 | struct list_head *p;
71 | strim(path);
72 | write_index_lock();
73 | list_for_each(p, &protect_list) {
74 | s = list_entry(p, node, list);
75 | if (strcmp(s->path, path) == 0) {
76 | list_del(p);
77 | write_index_unlock();
78 | return ;
79 | }
80 | }
81 | write_index_unlock();
82 | printk("[*] Del Protect List: %s\n", path);
83 | }
84 |
85 | int checkpath(char *path) {
86 | node *s;
87 | struct list_head *p;
88 | strim(path);
89 | list_for_each(p, &protect_list) {
90 | s = list_entry(p, node, list);
91 | strim(s->path);
92 | if(strlen(s->path) > 4) {
93 | if(strstr((const char*)path, (const char*)s->path) != NULL) {
94 | return 1;
95 | }
96 | }
97 | }
98 | return 0;
99 | }
100 |
101 | static void add_protect_list(char *data)
102 | {
103 | node *s = NULL;
104 | write_index_lock();
105 | strim(data);
106 | if(strlen(data) > 4) {
107 | s = (node *)kmalloc(sizeof(node), GFP_ATOMIC);
108 | s->path = data;
109 | list_add_tail(&(s->list), &protect_list);
110 | printk("[*] Add Protect List: %s\n", data);
111 | }
112 | write_index_unlock();
113 | }
114 |
115 | static ssize_t device_write(struct file *file,const char __user * buffer, size_t length, loff_t * offset)
116 | {
117 | int i;
118 | int flag = 0;
119 | char path[PATH_MAX] = "";
120 |
121 | for (i = 0; i < length && i < PATH_MAX; i++) {
122 | get_user(path[i], buffer + i);
123 |
124 | if(i == 0 && strcmp(path, "+") == 0) {
125 | flag = 1;
126 | continue;
127 | }
128 |
129 |
130 | if(i == 0 && strcmp(path, "-") == 0) {
131 | flag = 2;
132 | continue;
133 | }
134 | }
135 |
136 | if(flag == 1)
137 | add_protect_list(path+1);
138 |
139 | if(flag == 2)
140 | del_protect_list(path+1);
141 |
142 | return i;
143 | }
144 |
145 | static int device_mmap(struct file *filp, struct vm_area_struct *vma)
146 | {
147 | int ret = 0;
148 | struct page *page = NULL;
149 | unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
150 |
151 | vma->vm_flags |= 0;
152 |
153 | if (size > MAX_SIZE) {
154 | ret = -EINVAL;
155 | goto out;
156 | }
157 |
158 | page = virt_to_page((unsigned long)sh_mem + (vma->vm_pgoff << PAGE_SHIFT));
159 | ret = remap_pfn_range(vma, vma->vm_start, page_to_pfn(page), size, vma->vm_page_prot);
160 | if (ret != 0) {
161 | goto out;
162 | }
163 |
164 | out:
165 | return ret;
166 | }
167 |
168 | int protected_init(void)
169 | {
170 | INIT_LIST_HEAD(&protect_list);
171 | return 0;
172 | }
173 |
174 | int init_share_mem(void)
175 | {
176 | int i;
177 | share_mem_flag = -1;
178 |
179 | protected_init();
180 |
181 | major = register_chrdev(0, DEVICE_NAME, &mchar_fops);
182 |
183 | if (major < 0) {
184 | pr_err("[SMITH] REGISTER_CHRDEV_ERROR\n");
185 | return -1;
186 | }
187 |
188 | class = class_create(THIS_MODULE, CLASS_NAME);
189 | if (IS_ERR(class)) {
190 | unregister_chrdev(major, DEVICE_NAME);
191 | pr_err("[SMITH] CLASS_CREATE_ERROR");
192 | return -1;
193 | }
194 |
195 | device = device_create(class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
196 | if (IS_ERR(device)) {
197 | class_destroy(class);
198 | unregister_chrdev(major, DEVICE_NAME);
199 | pr_err("[SMITH] DEVICE_CREATE_ERROR");
200 | return -1;
201 | }
202 |
203 | sh_mem = kzalloc(MAX_SIZE, GFP_KERNEL);
204 |
205 | if (sh_mem == NULL) {
206 | device_destroy(class, MKDEV(major, 0));
207 | class_destroy(class);
208 | unregister_chrdev(major, DEVICE_NAME);
209 | pr_err("[SMITH] SHMEM_INIT_ERROR\n");
210 | return -ENOMEM;
211 | }
212 | else {
213 | for (i = 0; i < MAX_SIZE; i += PAGE_SIZE)
214 | SetPageReserved(virt_to_page(((unsigned long)sh_mem) + i));
215 | }
216 |
217 | mutex_init(&mchar_mutex);
218 | lock_init();
219 | return 0;
220 | }
221 |
222 | void uninstall_share_mem(void)
223 | {
224 | device_destroy(class, MKDEV(major, 0));
225 | class_unregister(class);
226 | class_destroy(class);
227 | unregister_chrdev(major, DEVICE_NAME);
228 | }
--------------------------------------------------------------------------------
/lkm/share_mem.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************
2 | * Project: AgentSmith-HIDS
3 | * Author: E_BWill
4 | * Year: 2018
5 | * File: smith_hook.h
6 | * Description: share memory
7 | *******************************************************************/
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #define DEVICE_NAME "smith"
19 | #define CLASS_NAME "smith"
20 |
21 | #define MAX_SIZE 2097152
22 | #define CHECK_READ_INDEX_THRESHOLD 524288
23 | #define CHECK_WRITE_INDEX_THRESHOLD 32768
24 |
25 | #define DELAY_TEST 0
26 | #define KERNEL_PRINT 0
27 |
28 | extern int share_mem_flag;
29 |
30 | int init_share_mem(void);
31 | int send_msg_to_user(char *msg, int kfree_flag);
32 | void uninstall_share_mem(void);
33 | int checkpath(char *path);
--------------------------------------------------------------------------------
/lkm/smith_hook.c:
--------------------------------------------------------------------------------
1 |
2 | #include "share_mem.h"
3 | #include "smith_hook.h"
4 | #include "struct_wrap.h"
5 |
6 | #define EXIT_PROTECT 0
7 |
8 | int share_mem_flag = -1;
9 | char fsnotify_kprobe_state = 0x0;
10 |
11 | static char *str_replace(char *orig, char *rep, char *with)
12 | {
13 | char *result, *ins, *tmp;
14 | int len_rep, len_with, len_front, count;
15 |
16 | if (!orig || !rep)
17 | return NULL;
18 |
19 | len_rep = strlen(rep);
20 | if (len_rep == 0)
21 | return NULL;
22 |
23 | if (!with)
24 | with = "";
25 |
26 | len_with = strlen(with);
27 |
28 | ins = orig;
29 | for (count = 0; (tmp = strstr(ins, rep)); ++count)
30 | ins = tmp + len_rep;
31 |
32 | tmp = result = kzalloc(strlen(orig) + (len_with - len_rep) * count + 1, GFP_ATOMIC);
33 |
34 | if (!result)
35 | return NULL;
36 |
37 | while (count--) {
38 | ins = strstr(orig, rep);
39 | len_front = ins - orig;
40 | tmp = strncpy(tmp, orig, len_front) + len_front;
41 | tmp = strcpy(tmp, with) + len_with;
42 | orig += len_front + len_rep;
43 | }
44 |
45 | strcpy(tmp, orig);
46 | return result;
47 | }
48 |
49 | static inline int _kill_task_by_task(struct task_struct *p_task, char *path) {
50 | int uid = get_current_uid();
51 | if(current->pid > 1000 && current->real_parent->pid > 1000) {
52 | printk("[!!!] Don't Touch Me(%s) %d|%d!\n",path, uid, current->pid);
53 | return send_sig_info(SIGKILL, SEND_SIG_PRIV, p_task);
54 | }
55 | return 0;
56 | }
57 |
58 | static inline int _kill_task_by_pid(pid_t p_pid) {
59 | return _kill_task_by_task(pid_task(find_vpid(p_pid), PIDTYPE_PID), "");
60 | }
61 |
62 | static void fsnotify_post_handler(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
63 | {
64 | struct path *path;
65 | __u32 flag = (__u32)p_get_arg2(regs);
66 | if (flag == FS_OPEN || flag == FS_ACCESS) {
67 | char buffer[PATH_MAX];
68 | memset(buffer, 0, sizeof(PATH_MAX));
69 | path = (struct path *)p_get_arg3(regs);
70 | char *pathstr = dentry_path_raw(path->dentry, buffer, PATH_MAX);
71 |
72 | if(strlen(pathstr) > 5 && checkpath(pathstr) == 1)
73 | _kill_task_by_task(current, pathstr);
74 | }
75 | }
76 |
77 | static struct kprobe fsnotify_kprobe = {
78 | .symbol_name = "fsnotify",
79 | .post_handler = fsnotify_post_handler,
80 | };
81 |
82 | static int fsnotify_register_kprobe(void)
83 | {
84 | int ret;
85 | ret = register_kprobe(&fsnotify_kprobe);
86 |
87 | if (ret == 0)
88 | fsnotify_kprobe_state = 0x1;
89 |
90 | return ret;
91 | }
92 |
93 | static void unregister_kprobe_fsnotify(void)
94 | {
95 | unregister_kprobe(&fsnotify_kprobe);
96 | }
97 |
98 | static void uninstall_kprobe(void)
99 | {
100 | if (fsnotify_kprobe_state == 0x1)
101 | unregister_kprobe_fsnotify();
102 | }
103 |
104 | static int __init smith_init(void)
105 | {
106 | int ret;
107 |
108 | ret = init_share_mem();
109 |
110 | if (ret != 0)
111 | return ret;
112 | else
113 | printk(KERN_INFO "[SMITH] init_share_mem success \n");
114 |
115 | ret = fsnotify_register_kprobe();
116 | if (ret < 0) {
117 | uninstall_kprobe();
118 | uninstall_share_mem();
119 | printk(KERN_INFO "[SMITH] fsnotify register_kprobe failed, returned %d\n", ret);
120 | return -1;
121 | }
122 |
123 | return 0;
124 | }
125 |
126 | static void __exit smith_exit(void)
127 | {
128 | uninstall_kprobe();
129 | uninstall_share_mem();
130 | printk(KERN_INFO "[SMITH] uninstall_kprobe success\n");
131 | }
132 |
133 | module_init(smith_init)
134 | module_exit(smith_exit)
135 |
136 | MODULE_LICENSE("GPL v2");
137 | MODULE_VERSION("0.0.1");
138 | MODULE_AUTHOR("E_Bwill ");
--------------------------------------------------------------------------------
/lkm/smith_hook.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #define SMITH_NAME_MAX (PATH_MAX - sizeof(struct filename))
27 |
28 | typedef unsigned short int uint16;
29 | typedef unsigned long int uint32;
30 |
31 | #define NIPQUAD(addr) \
32 | ((unsigned char *)&addr)[0], \
33 | ((unsigned char *)&addr)[1], \
34 | ((unsigned char *)&addr)[2], \
35 | ((unsigned char *)&addr)[3]
36 |
37 | #define NIP6(addr) \
38 | ntohs((addr).s6_addr16[0]), \
39 | ntohs((addr).s6_addr16[1]), \
40 | ntohs((addr).s6_addr16[2]), \
41 | ntohs((addr).s6_addr16[3]), \
42 | ntohs((addr).s6_addr16[4]), \
43 | ntohs((addr).s6_addr16[5]), \
44 | ntohs((addr).s6_addr16[6]), \
45 | ntohs((addr).s6_addr16[7])
46 |
47 | #define BigLittleSwap16(A) ((((uint16)(A)&0xff00) >> 8) | \
48 | (((uint16)(A)&0x10ff) << 8))
49 |
50 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
51 | #define P_SYSCALL_LAYOUT_4_17
52 | #ifdef CONFIG_X86_64
53 | #define P_SYSCALL_PREFIX(x) P_TO_STRING(__x64_sys_ ## x)
54 | #else
55 | #define P_SYSCALL_PREFIX(x) P_TO_STRING(sys_ ## x)
56 | #endif
57 | #else
58 | #define P_SYSCALL_PREFIX(x) P_TO_STRING(sys_ ## x)
59 | #endif
60 |
61 | #define P_TO_STRING(x) # x
62 | #define P_GET_SYSCALL_NAME(x) P_SYSCALL_PREFIX(x)
63 |
--------------------------------------------------------------------------------
/lkm/struct_wrap.h:
--------------------------------------------------------------------------------
1 | #ifdef CONFIG_X86
2 | static inline unsigned long p_regs_get_arg1(struct pt_regs *p_regs) {
3 | return p_regs->di;
4 | }
5 |
6 | static inline unsigned long p_regs_get_arg2(struct pt_regs *p_regs) {
7 | return p_regs->si;
8 | }
9 |
10 | static inline unsigned long p_regs_get_arg3(struct pt_regs *p_regs) {
11 | return p_regs->dx;
12 | }
13 |
14 | static inline unsigned long p_regs_get_arg4(struct pt_regs *p_regs) {
15 | return p_regs->r10;
16 | }
17 |
18 | static inline unsigned long p_regs_get_arg5(struct pt_regs *p_regs) {
19 | return p_regs->r8;
20 | }
21 |
22 | static inline unsigned long p_regs_get_arg6(struct pt_regs *p_regs) {
23 | return p_regs->r9;
24 | }
25 |
26 | static inline unsigned long p_get_arg1(struct pt_regs *p_regs) {
27 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
28 | return p_regs_get_arg1((struct pt_regs *)p_regs_get_arg1(p_regs));
29 | #else
30 | return p_regs_get_arg1(p_regs);
31 | #endif
32 | }
33 |
34 | static inline unsigned long p_get_arg2(struct pt_regs *p_regs) {
35 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
36 | return p_regs_get_arg2((struct pt_regs *)p_regs_get_arg1(p_regs));
37 | #else
38 | return p_regs_get_arg2(p_regs);
39 | #endif
40 | }
41 |
42 | static inline unsigned long p_get_arg3(struct pt_regs *p_regs) {
43 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
44 | return p_regs_get_arg3((struct pt_regs *)p_regs_get_arg1(p_regs));
45 | #else
46 | return p_regs_get_arg3(p_regs);
47 | #endif
48 | }
49 |
50 | static inline unsigned long p_get_arg4(struct pt_regs *p_regs) {
51 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
52 | return p_regs_get_arg4((struct pt_regs *)p_regs_get_arg1(p_regs));
53 | #else
54 | return p_regs_get_arg4(p_regs);
55 | #endif
56 | }
57 |
58 | static inline unsigned long p_get_arg5(struct pt_regs *p_regs) {
59 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
60 | return p_regs_get_arg5((struct pt_regs *)p_regs_get_arg1(p_regs));
61 | #else
62 | return p_regs_get_arg5(p_regs);
63 | #endif
64 | }
65 |
66 | static inline unsigned long p_get_arg6(struct pt_regs *p_regs) {
67 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) && defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER)
68 | return p_regs_get_arg6((struct pt_regs *)p_regs_get_arg1(p_regs));
69 | #else
70 | return p_regs_get_arg6(p_regs);
71 | #endif
72 | }
73 | #endif
74 |
75 | static inline int get_current_uid(void) {
76 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
77 | return current->real_cred->uid.val;
78 | #else
79 | return current->real_cred->uid;
80 | #endif
81 | }
--------------------------------------------------------------------------------
/pkg/agent/fsnotify.go:
--------------------------------------------------------------------------------
1 | package agent
2 |
3 | import (
4 | "github.com/fsnotify/fsnotify"
5 | "log"
6 | )
7 |
8 | type FileWatcherMsg struct {
9 | File string
10 | Level string
11 | Msg string
12 | }
13 |
14 | func GetNewFileWatcherMsgChan() chan FileWatcherMsg {
15 | return make(chan FileWatcherMsg)
16 | }
17 |
18 | func AddNewWatcher(path string, msgChan chan FileWatcherMsg) {
19 | watch, err := fsnotify.NewWatcher()
20 | if err != nil {
21 | log.Fatal(err)
22 | }
23 | defer watch.Close()
24 | _ = watch.Add(path)
25 |
26 | for {
27 | select {
28 | case ev := <-watch.Events:
29 | {
30 | if ev.Op&fsnotify.Write == fsnotify.Write {
31 | msgChan <- FileWatcherMsg{
32 | File: path,
33 | Level: "danger",
34 | Msg: "File Writed",
35 | }
36 | }
37 |
38 | if ev.Op&fsnotify.Remove == fsnotify.Remove {
39 | msgChan <- FileWatcherMsg{
40 | File: path,
41 | Level: "danger",
42 | Msg: "File Remove",
43 | }
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/agent/loadder.go:
--------------------------------------------------------------------------------
1 | package agent
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "os"
7 | "os/user"
8 | "strconv"
9 | "syscall"
10 | "unsafe"
11 | )
12 |
13 | const (
14 | PTRACE = 101
15 | MFD_CREATE = 319
16 | MFD_CLOEXEC = 0x0001
17 | PTRACE_SEIZE = 0x4206
18 | )
19 |
20 | type MemFD struct {
21 | *os.File
22 | }
23 |
24 | func ReadFile(filePth string) ([]byte, error) {
25 | f, err := os.Open(filePth)
26 | if err != nil {
27 | return nil, err
28 | }
29 |
30 | return ioutil.ReadAll(f)
31 | }
32 |
33 | func CreateMemfd(name string) *MemFD {
34 | fd, _, _ := syscall.Syscall(MFD_CREATE, uintptr(unsafe.Pointer(&name)), uintptr(MFD_CLOEXEC), 0)
35 | return &MemFD{
36 | os.NewFile(fd, name),
37 | }
38 | }
39 |
40 | func (self *MemFD) Write(bytes []byte) (int, error) {
41 | return syscall.Write(int(self.Fd()), bytes)
42 | }
43 |
44 | func (self *MemFD) Path() string {
45 | return fmt.Sprintf("/proc/self/fd/%d", self.Fd())
46 | }
47 |
48 | func (self *MemFD) ExecuteWithAttributes(procAttr *syscall.ProcAttr, arguments ...string) (int, uintptr, error) {
49 | return syscall.StartProcess(self.Path(), append([]string{self.Name()}, arguments...), procAttr)
50 | }
51 |
52 | func DenyPtrace(pid int) (err error) {
53 | _, _, e := syscall.Syscall6(PTRACE, uintptr(PTRACE_SEIZE), uintptr(pid), uintptr(0), uintptr(0), uintptr(0), uintptr(0))
54 | if e != 0 {
55 | err = syscall.Errno(e)
56 | return err
57 | }
58 | return
59 | }
60 |
61 | func ExecveMemfdFromBytes(process_name string, data []byte, user_name string, ptrace bool, argv []string, envv []string) (*os.Process, error) {
62 | if user_name == "" {
63 | user_name = "nobody"
64 | }
65 |
66 | user_info, err := user.Lookup(user_name)
67 | if err != nil {
68 | return nil, err
69 | }
70 |
71 | uid, _ := strconv.Atoi(user_info.Uid)
72 | gid, _ := strconv.Atoi(user_info.Gid)
73 |
74 | memfd := CreateMemfd(process_name)
75 | _, err = memfd.Write(data)
76 | if err != nil {
77 | return nil, err
78 | }
79 |
80 | os_envv := os.Environ()
81 |
82 | for i := range envv {
83 | os_envv = append(os_envv, envv[i])
84 | }
85 |
86 | procAttr := &os.ProcAttr{
87 | Env: os_envv,
88 | Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
89 | Sys: &syscall.SysProcAttr{
90 | Credential: &syscall.Credential{
91 | Uid: uint32(uid),
92 | Gid: uint32(gid),
93 | },
94 | Setsid: true,
95 | },
96 | }
97 |
98 | process, err := os.StartProcess(memfd.Path(), append([]string{process_name}, argv...), procAttr)
99 |
100 | if err != nil {
101 | return process, err
102 | }
103 |
104 | if !ptrace {
105 | err = DenyPtrace(process.Pid)
106 | if err != nil {
107 | _ = process.Kill()
108 | return process, err
109 | }
110 | }
111 |
112 | return process, err
113 | }
114 |
115 | func ExecveMemfdFromFile(path string, user_name string, ptrace bool, argv []string, envv []string) (*os.Process, error) {
116 | data, err := ReadFile(path)
117 |
118 | if err != nil {
119 | return nil, err
120 | }
121 |
122 | user_info, err := user.Lookup(user_name)
123 | if err != nil {
124 | return nil, err
125 | }
126 |
127 | uid, _ := strconv.Atoi(user_info.Uid)
128 | gid, _ := strconv.Atoi(user_info.Gid)
129 |
130 | memfd := CreateMemfd(path)
131 | _, err = memfd.Write(data)
132 | if err != nil {
133 | return nil, err
134 | }
135 |
136 | os_envv := os.Environ()
137 |
138 | for i := range envv {
139 | os_envv = append(os_envv, envv[i])
140 | }
141 |
142 | procAttr := &os.ProcAttr{
143 | Env: os_envv,
144 | Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
145 | Sys: &syscall.SysProcAttr{
146 | Credential: &syscall.Credential{
147 | Uid: uint32(uid),
148 | Gid: uint32(gid),
149 | },
150 | Setsid: true,
151 | },
152 | }
153 |
154 | process, err := os.StartProcess(memfd.Path(), append([]string{path}, argv...), procAttr)
155 |
156 | if err != nil {
157 | return process, err
158 | }
159 |
160 | if !ptrace {
161 | err = DenyPtrace(process.Pid)
162 | if err != nil {
163 | _ = process.Kill()
164 | return process, err
165 | }
166 | }
167 |
168 | return process, err
169 | }
170 |
--------------------------------------------------------------------------------
/pkg/agent/loadder_test.go:
--------------------------------------------------------------------------------
1 | package agent
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestLoad(t *testing.T) {
9 | process, err := ExecveMemfd("/root/gohack/test", "nobody", false, []string{}, []string{})
10 | if err != nil {
11 | fmt.Println("ERROR!", err)
12 | }
13 | fmt.Println(process.Pid)
14 | _, _ = process.Wait()
15 | }
16 |
--------------------------------------------------------------------------------
/pkg/app/app.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "encoding/json"
5 | "github.com/google/uuid"
6 | _ "github.com/google/uuid"
7 | "log"
8 | )
9 |
10 | type App struct {
11 | Appid uuid.UUID
12 | ExecInfo Executable
13 | SourceInfo Source
14 | DNS string
15 | }
16 |
17 | type Executable struct {
18 | AbsPath string
19 | Argv string
20 | Envv string
21 | Ptrace bool
22 | UserName string
23 | }
24 |
25 | type Source struct {
26 | Language string
27 | }
28 |
29 | // dumps to json
30 | func (app App) Dumps() string {
31 | b, err := json.Marshal(app)
32 | if err != nil {
33 | log.Fatalln(err)
34 | }
35 | return string(b)
36 | }
37 |
38 | // loads from string
39 | func (app *App) Loads(appJson string) {
40 | err := json.Unmarshal([]byte(appJson), &app)
41 | if err != nil {
42 | log.Fatalln(err)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/app/app_test.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "github.com/google/uuid"
5 | "testing"
6 | )
7 |
8 | func TestApp(t *testing.T) {
9 | execuable := Executable{"~/.bin/test"}
10 | source := Source{"go"}
11 | app := App{uuid.New(), execuable, source}
12 | appDumped := app.Dumps()
13 | appLoaded := new(App)
14 | appLoaded.Loads(appDumped)
15 | if appLoaded.Appid != app.Appid {
16 | t.Error(
17 | "expected", app.Appid,
18 | "got", appLoaded.Appid,
19 | )
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/pkg/client/appinfo_test.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | "youzoo/why/pkg/app"
7 | )
8 |
9 | func TestFetchAppInfo(t *testing.T) {
10 | appinfo := app.App{}
11 | FetchAppInfo("localhost:5000", "679a2d46-8313-48f2-8d4b-915107b78eda", &appinfo)
12 | fmt.Println(appinfo)
13 | }
--------------------------------------------------------------------------------
/pkg/client/client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "net/http"
7 | "time"
8 | )
9 |
10 | var httpClient = &http.Client{Timeout: 10 * time.Second}
11 |
12 | func FetchPubKey(host string, appid string, target interface{}) error {
13 | resp, err := httpClient.Get(
14 | "http://" + host + "/key/pub/" + appid,
15 | )
16 | if err != nil {
17 | panic(err)
18 | }
19 | defer resp.Body.Close()
20 | return json.NewDecoder(resp.Body).Decode(target)
21 | }
22 |
23 | func FetchPriKey(host string, appid string, target interface{}) error {
24 | resp, err := httpClient.Get(
25 | "http://" + host + "/key/pri/" + appid,
26 | )
27 | if err != nil {
28 | panic(err)
29 | }
30 | defer resp.Body.Close()
31 | return json.NewDecoder(resp.Body).Decode(target)
32 | }
33 |
34 | func FetchAppInfo(host string, appid string, target interface{}) error {
35 | resp, err := httpClient.Get(
36 | "http://" + host + "/app/" + appid,
37 | )
38 | if err != nil {
39 | panic(err)
40 | }
41 | defer resp.Body.Close()
42 | return json.NewDecoder(resp.Body).Decode(target)
43 | }
44 |
45 | func NewAlert(host string, appid string, target interface{}) error {
46 | jsonStr, err := json.Marshal(target)
47 | if err != nil {
48 | panic(err)
49 | }
50 | resp, err := httpClient.Post(
51 | "http://"+host+"/alert/new",
52 | "application/json",
53 | bytes.NewBuffer(jsonStr))
54 | defer resp.Body.Close()
55 | return json.NewDecoder(resp.Body).Decode(target)
56 | }
57 |
--------------------------------------------------------------------------------
/pkg/common/until.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "crypto/md5"
5 | "encoding/hex"
6 | "fmt"
7 | "io/ioutil"
8 | "os"
9 | "strings"
10 | )
11 |
12 | var (
13 | GreenBg = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
14 | WhiteBg = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
15 | YellowBg = string([]byte{27, 91, 57, 48, 59, 52, 51, 109})
16 | RedBg = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
17 | BlueBg = string([]byte{27, 91, 57, 55, 59, 52, 52, 109})
18 | MagentaBg = string([]byte{27, 91, 57, 55, 59, 52, 53, 109})
19 | CyanBg = string([]byte{27, 91, 57, 55, 59, 52, 54, 109})
20 | Green = string([]byte{27, 91, 51, 50, 109})
21 | White = string([]byte{27, 91, 51, 55, 109})
22 | Yellow = string([]byte{27, 91, 51, 51, 109})
23 | Red = string([]byte{27, 91, 51, 49, 109})
24 | Blue = string([]byte{27, 91, 51, 52, 109})
25 | Magenta = string([]byte{27, 91, 51, 53, 109})
26 | Cyan = string([]byte{27, 91, 51, 54, 109})
27 | Reset = string([]byte{27, 91, 48, 109})
28 | DisableColor = false
29 | )
30 |
31 | func GetDNSServer() string {
32 | f, err := os.Open("/etc/resolv.conf")
33 | if err != nil {
34 | return ""
35 | }
36 |
37 | ori_data, err := ioutil.ReadAll(f)
38 | ori_str := string(ori_data)
39 | ori_list := strings.Split(ori_str, "\n")
40 | dns := strings.ReplaceAll(ori_list[0], "nameserver", "")
41 | return strings.TrimSpace(dns)
42 | }
43 |
44 | func GetBytesMD5(data []byte) string {
45 | hasher := md5.New()
46 | hasher.Write(data)
47 | return hex.EncodeToString(hasher.Sum(nil))
48 | }
49 |
50 | func GetFileMD5(fileAbsPath string) (string, error) {
51 | f, err := os.Open(fileAbsPath)
52 | if err != nil {
53 | return "", err
54 | }
55 | defer f.Close()
56 | fi, _ := f.Stat()
57 | si := fi.Size()
58 | fileBytes := make([]byte, si)
59 |
60 | _, err = f.Read(fileBytes)
61 | if err != nil {
62 | return "", err
63 | }
64 |
65 | return GetBytesMD5(fileBytes), nil
66 | }
67 |
68 | func Info(msg string) {
69 | fmt.Println(GreenBg, "[+] Info:", msg, Reset)
70 | }
71 | func Error(msg string) {
72 | fmt.Println(RedBg, "[!] Error:", msg, Reset)
73 | }
--------------------------------------------------------------------------------
/pkg/crypto/crypto.go:
--------------------------------------------------------------------------------
1 | package crypto
2 |
3 | import (
4 | "crypto/rand"
5 | "crypto/rsa"
6 | "crypto/sha512"
7 | "crypto/x509"
8 | "encoding/base64"
9 | "encoding/pem"
10 | "log"
11 | )
12 |
13 | func GenerateKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey) {
14 | privKey, err := rsa.GenerateKey(rand.Reader, bits)
15 | if err != nil {
16 | log.Fatalln(err)
17 | }
18 | return privKey, &privKey.PublicKey
19 | }
20 |
21 | func PrivateKeyToBytes(priv *rsa.PrivateKey) []byte {
22 | privBytes := pem.EncodeToMemory(
23 | &pem.Block{
24 | Type: "RSA PRIVATE KEY",
25 | Bytes: x509.MarshalPKCS1PrivateKey(priv),
26 | })
27 | return privBytes
28 |
29 | }
30 |
31 | func PublicKeyToBytes(pub *rsa.PublicKey) []byte {
32 | pubASN1, err := x509.MarshalPKIXPublicKey(pub)
33 | if err != nil {
34 | log.Fatalln(err)
35 | }
36 | pubBytes := pem.EncodeToMemory(&pem.Block{
37 | Type: "RSA PUBLIC KEY",
38 | Bytes: pubASN1,
39 | })
40 | return pubBytes
41 | }
42 |
43 | func BytesToPrivateKey(priv []byte) *rsa.PrivateKey {
44 | block, _ := pem.Decode(priv)
45 | enc := x509.IsEncryptedPEMBlock(block)
46 | b := block.Bytes
47 | var err error
48 | if enc {
49 | log.Println("is encrypted pem block")
50 | b, err = x509.DecryptPEMBlock(block, nil)
51 | if err != nil {
52 | log.Fatalln(err)
53 | }
54 |
55 | }
56 | key, err := x509.ParsePKCS1PrivateKey(b)
57 | if err != nil {
58 | log.Fatalln(err)
59 | }
60 | return key
61 | }
62 |
63 | func BytesToPublicKey(pub []byte) *rsa.PublicKey {
64 | block, _ := pem.Decode(pub)
65 | enc := x509.IsEncryptedPEMBlock(block)
66 | b := block.Bytes
67 | var err error
68 | if enc {
69 | log.Println("is encrypted pem block")
70 | b, err = x509.DecryptPEMBlock(block, nil)
71 | if err != nil {
72 | log.Fatalln(err)
73 | }
74 | }
75 | ifc, err := x509.ParsePKIXPublicKey(b)
76 | if err != nil {
77 | log.Fatalln(err)
78 | }
79 | key, ok := ifc.(*rsa.PublicKey)
80 | if !ok {
81 | log.Fatalln("not ok")
82 | }
83 |
84 | return key
85 | }
86 |
87 | func EncryptWithPublicKey(msg []byte, pub *rsa.PublicKey) []byte {
88 | hash := sha512.New()
89 | ciphertext, err := rsa.EncryptOAEP(hash, rand.Reader, pub, msg, nil)
90 | if err != nil {
91 | log.Fatalln(err)
92 | }
93 | return ciphertext
94 | }
95 |
96 | func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte {
97 | hash := sha512.New()
98 | plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil)
99 | if err != nil {
100 | log.Fatalln(err)
101 | }
102 | return plaintext
103 | }
104 |
105 | func BytesBase64Encode(bytes []byte) []byte {
106 | dst := make([]byte, base64.StdEncoding.EncodedLen(len(bytes)))
107 | base64.StdEncoding.Encode(dst, bytes)
108 | return dst
109 | }
110 | func BytesBase64Decode(bytes []byte) []byte {
111 | dst := make([]byte, base64.StdEncoding.DecodedLen(len(bytes)))
112 | n, err := base64.StdEncoding.Decode(dst, bytes)
113 | if err != nil {
114 | log.Fatalln(err)
115 | }
116 | return dst[:n]
117 | }
118 |
--------------------------------------------------------------------------------
/pkg/crypto/crypto_test.go:
--------------------------------------------------------------------------------
1 | package crypto
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestCrypto(t *testing.T) {
9 | //fmt.Println("test RSA")
10 | priv, pub := GenerateKeyPair(2048)
11 | fmt.Println("pub key: ", string(PublicKeyToBytes(pub)))
12 | fmt.Println("priv key: ", string(PrivateKeyToBytes(priv)))
13 | plaintext := []byte("gaba gaba gaba hey")
14 | plaintextBase64Encoded := BytesBase64Encode(plaintext)
15 | //ciphertext := EncryptWithPublicKey(plaintextBase64Encoded, pub)
16 | ciphertext := EncryptWithPublicKey(plaintextBase64Encoded, BytesToPublicKey([]byte(string(PublicKeyToBytes(pub)))))
17 | ciphertextBase64Encoded := BytesBase64Encode(ciphertext)
18 | ciphertextBase64Decoded := BytesBase64Decode(ciphertextBase64Encoded)
19 |
20 | decryptedtext := DecryptWithPrivateKey(ciphertextBase64Decoded, priv)
21 | decryptedtextBase64Decoded := BytesBase64Decode(decryptedtext)
22 |
23 | fmt.Println(string(plaintext))
24 | fmt.Println(string(ciphertextBase64Encoded))
25 | fmt.Println(string(decryptedtextBase64Decoded))
26 | if string(plaintext) != string(decryptedtextBase64Decoded) {
27 | t.Error(
28 | "expected", plaintext,
29 | "got", decryptedtextBase64Decoded,
30 | )
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/elf/elf.go:
--------------------------------------------------------------------------------
1 | package elf
2 |
3 | import (
4 | "debug/elf"
5 | "encoding/binary"
6 | "encoding/hex"
7 | "fmt"
8 | "io"
9 | "os"
10 | "youzoo/why/pkg/crypto"
11 | )
12 |
13 | const (
14 | MagicNumber = "31F"
15 | )
16 |
17 | func check(e error) {
18 | if e != nil {
19 | panic(e)
20 | }
21 | }
22 |
23 | func OpenFile(file string) io.ReaderAt {
24 | r, err := os.Open(file)
25 | check(err)
26 | return r
27 | }
28 |
29 | func LoadELF(absFilePath string) *elf.File {
30 | f := OpenFile(absFilePath)
31 | err := MagicNumberCheck(f)
32 | check(err)
33 | _elf, err := elf.NewFile(f)
34 | check(err)
35 | return _elf
36 | }
37 |
38 | func MagicNumberCheck(f io.ReaderAt) error {
39 | // Read and decode ELF identifier
40 | var ident [16]uint8
41 | _, err := f.ReadAt(ident[0:], 0)
42 | check(err)
43 | if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
44 | err := fmt.Errorf("Bad magic number at %d\n", ident[0:4])
45 | return err
46 | }
47 | return nil
48 | }
49 |
50 | type Chunk struct {
51 | Data []byte
52 | EncryptFlag bool
53 | }
54 | type Chunks []Chunk
55 |
56 | // Chunks, LastChunk
57 | func SplitELF(fileAbsPath string) (Chunks, Chunk) {
58 | f, err := os.Open(fileAbsPath)
59 | check(err)
60 | defer f.Close()
61 | // file length
62 | fi, err := f.Stat()
63 | check(err)
64 | size := fi.Size()
65 | extraBytes := size % 64
66 | times := (size - extraBytes) / 64
67 |
68 | // extraBytes will append bottom
69 | var chunks Chunks
70 | for i := int64(0); i < times; i++ {
71 | tmpBytes := make([]byte, 64)
72 | _, err := f.Read(tmpBytes)
73 | check(err)
74 | chunks = append(chunks, Chunk{Data: tmpBytes, EncryptFlag: Even(i)})
75 | }
76 | tmpBytes := make([]byte, extraBytes)
77 | _, err = f.Read(tmpBytes)
78 | if err != nil {
79 | if err.Error() != "EOF" {
80 | check(err)
81 | }
82 | }
83 | lastChunk := Chunk{tmpBytes, false}
84 | return chunks, lastChunk
85 | }
86 |
87 | func WriteChunk(fileAbsPath string, chunks Chunks) {
88 | f, err := os.Create(fileAbsPath)
89 | check(err)
90 | defer f.Close()
91 |
92 | for _, chunk := range chunks {
93 | _, err := f.Write(chunk.Data)
94 | check(err)
95 | }
96 | }
97 |
98 | func Even(number int64) bool {
99 | return number%2 == 0
100 | }
101 | func Odd(number int64) bool {
102 | return !Even(number)
103 | }
104 |
105 | func ChunkDumper(chunk Chunk) {
106 | // dumper
107 | fmt.Printf("%d bytes:\n", len(chunk.Data))
108 | dumper := hex.Dumper(os.Stdout)
109 | defer dumper.Close()
110 | _, _ = dumper.Write(chunk.Data)
111 | }
112 |
113 | func EncryptChunk(chunk Chunk, pubKeyBytes []byte) Chunk {
114 | pubKey := crypto.BytesToPublicKey(pubKeyBytes)
115 | encryptData := crypto.EncryptWithPublicKey(chunk.Data, pubKey)
116 | chunk.Data = encryptData
117 | return chunk
118 | }
119 |
120 | func DecryptChunk(chunk Chunk, priKeyBytes []byte) Chunk {
121 | priKey := crypto.BytesToPrivateKey(priKeyBytes)
122 | decryptData := crypto.DecryptWithPrivateKey(chunk.Data, priKey)
123 | chunk.Data = decryptData
124 | return chunk
125 |
126 | }
127 |
128 | func EncryptChunks(chunks Chunks, pubKeyBytes []byte) Chunks {
129 | var encryptChunks Chunks
130 | for _, chunk := range chunks {
131 | if chunk.EncryptFlag {
132 | encryptedChunk := EncryptChunk(chunk, pubKeyBytes)
133 | encryptChunks = append(encryptChunks, encryptedChunk)
134 |
135 | } else {
136 | encryptChunks = append(encryptChunks, chunk)
137 | }
138 | }
139 | return encryptChunks
140 | }
141 |
142 | func HeaderChunks(appid []byte, hash []byte) Chunks {
143 | magicNumber := []byte(MagicNumber)
144 | magicChunk := Chunk{magicNumber, false}
145 | appidChunk := Chunk{appid, false}
146 | hashChunk := Chunk{hash, true}
147 | return Chunks{magicChunk, appidChunk, hashChunk}
148 | }
149 |
150 | func IntToBytes(number uint32) []byte {
151 | bs := make([]byte, 5)
152 | binary.LittleEndian.PutUint32(bs, number)
153 | return bs
154 | }
155 | func BytesToInt(bs []byte) uint32 {
156 | number := binary.LittleEndian.Uint32(bs)
157 | return number
158 | }
159 |
160 | /*
161 | 3 bytes:
162 | 00000000 33 31 46 |31F|
163 | 5 bytes:
164 | 00000000 06 00 00 00 00 |.....|
165 | 6 bytes:
166 | 00000000 31 32 33 31 32 33 |123123|
167 | 256 bytes:
168 | 00000000 55 07 5b 00 46 50 1a f7 2f f7 37 54 1e bf 15 8e |U.[.FP../.7T....|
169 | 00000010 62 1d a8 9c 7a 96 89 ef de 83 3c 1d 91 9f 51 05 |b...z.....<...Q.|
170 | 00000020 d0 31 fa 08 f6 ff a5 03 9b ab d2 20 f2 79 74 d1 |.1......... .yt.|
171 | 00000030 bd 36 95 13 16 f3 ee 89 eb fb 7e ac 88 89 d1 d3 |.6........~.....|
172 | */
173 | func LoadEncryptedFileHeader(fileAbsPath string) (string, []byte) {
174 | f, err := os.Open(fileAbsPath)
175 | check(err)
176 | defer f.Close()
177 | magicNumber := make([]byte, 3)
178 | _, err = f.Read(magicNumber)
179 | check(err)
180 | // appid
181 | appid := make([]byte, 36)
182 | _, err = f.Read(appid)
183 | check(err)
184 | // hash
185 | hash := make([]byte, 256)
186 | _, err = f.Read(hash)
187 | check(err)
188 | return string(appid), hash
189 | }
190 |
191 | func LoadEncryptedFile(fileAbsPath string, priKey []byte) (string, []byte, []byte, error) {
192 | f, err := os.Open(fileAbsPath)
193 | check(err)
194 | defer f.Close()
195 | magicNumber := make([]byte, 3)
196 | _, err = f.Read(magicNumber)
197 | check(err)
198 | // appid
199 | appid := make([]byte, 36)
200 | _, err = f.Read(appid)
201 | check(err)
202 | // hash
203 | hash := make([]byte, 256)
204 | _, err = f.Read(hash)
205 | check(err)
206 |
207 | fi, _ := f.Stat()
208 | size := fi.Size()
209 | restFileLength := size - int64(3+36+256)
210 | var chunks Chunks
211 | next := 256
212 | for {
213 | var tmpBytes []byte
214 | if restFileLength < 64 {
215 | tmpBytes = make([]byte, restFileLength)
216 | _, _ = f.Read(tmpBytes)
217 | chunk := Chunk{tmpBytes, false}
218 | chunks = append(chunks, chunk)
219 | break
220 | } else {
221 | tmpBytes = make([]byte, next)
222 | }
223 | _, err := f.Read(tmpBytes)
224 | if err != nil {
225 | check(err)
226 | }
227 | if next == 256 {
228 | chunk := Chunk{tmpBytes, true}
229 | if restFileLength > 256 {
230 | restFileLength -= 256
231 | }
232 | next = 64
233 | chunks = append(chunks, chunk)
234 |
235 | } else {
236 | chunk := Chunk{tmpBytes, false}
237 | if restFileLength > 64 {
238 | restFileLength -= 64
239 | }
240 | next = 256
241 | chunks = append(chunks, chunk)
242 |
243 | }
244 |
245 | }
246 | //ChunkDumper(chunks[len(chunks)-1])
247 | var plainELF []byte
248 | for _, chunk := range chunks {
249 | if chunk.EncryptFlag {
250 | encryptedChunk := DecryptChunk(chunk, priKey)
251 | plainELF = append(plainELF, encryptedChunk.Data...)
252 |
253 | } else {
254 | plainELF = append(plainELF, chunk.Data...)
255 |
256 | }
257 | }
258 | return string(appid), hash, plainELF, nil
259 | }
260 |
--------------------------------------------------------------------------------
/pkg/elf/elf_test.go:
--------------------------------------------------------------------------------
1 | package elf
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "testing"
7 | "youzoo/why/pkg/crypto"
8 | )
9 |
10 | func TestELF(t *testing.T) {
11 | //_ := LoadELF("/opt/youzu/smith")
12 | chunks, extraChunk := SplitELF("/opt/youzu/ls")
13 | for _, chunk64 := range chunks {
14 | ChunkDumper(chunk64)
15 | }
16 | ChunkDumper(extraChunk)
17 | chunks = append(chunks, extraChunk)
18 | WriteChunk("/opt/youzu/ls_bak", chunks)
19 | }
20 |
21 | func TestEncrypt(t *testing.T) {
22 | chunks, extraChunk := SplitELF("/opt/youzu/ls")
23 | priv, pub := crypto.GenerateKeyPair(2048)
24 | encrptyChunk := EncryptChunk(extraChunk, crypto.PublicKeyToBytes(pub))
25 | decryptChunk := DecryptChunk(encrptyChunk, crypto.PrivateKeyToBytes(priv))
26 | fmt.Println(extraChunk)
27 | fmt.Println(encrptyChunk)
28 | fmt.Println(decryptChunk)
29 | for _, chunk64 := range chunks {
30 | encrptyChunk := EncryptChunk(chunk64, crypto.PublicKeyToBytes(pub))
31 | fmt.Println(len(chunk64.Data), len(encrptyChunk.Data))
32 | }
33 | }
34 |
35 | func TestEncryptChunks(t *testing.T) {
36 | chunks, extraChunk := SplitELF("/opt/youzu/main")
37 | ChunkDumper(extraChunk)
38 | pri, pub := crypto.GenerateKeyPair(2048)
39 | headerChunks := HeaderChunks([]byte("35097736-fb36-4c7e-9217-61794e9299dc"), []byte("6c6f31e624e2094dae7db53772855140"))
40 | // headerChunks + chunks + extraChunk
41 | fullChunks := append(headerChunks, chunks...)
42 | fullChunks = append(fullChunks, extraChunk)
43 | encryptChunks := EncryptChunks(fullChunks, crypto.PublicKeyToBytes(pub))
44 | for _, chunk := range encryptChunks[:10] {
45 | ChunkDumper(chunk)
46 | }
47 | ChunkDumper(fullChunks[len(fullChunks)-1])
48 | WriteChunk("/opt/youzu/main.encrypted", encryptChunks)
49 | _, _, elfBytes, _ := LoadEncryptedFile("/opt/youzu/main.encrypted", crypto.PrivateKeyToBytes(pri))
50 | f, err := os.Open("/opt/youzu/main")
51 | check(err)
52 | defer f.Close()
53 | tmpBytes := make([]byte, len(elfBytes))
54 | f.Read(tmpBytes)
55 | for i:=0;i&count=
40 | func AlertList(ctx iris.Context) {
41 | from := ctx.URLParamIntDefault("from", 0)
42 | count := ctx.URLParamIntDefault("count", 50)
43 | // search AppTable
44 | alerts, err := storage.ListAlert(from, count, db)
45 | if ErrorHandling(err, ctx) {
46 | return
47 | }
48 | _, _ = ctx.JSON(alerts)
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/web/app.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "github.com/google/uuid"
5 | "github.com/kataras/iris"
6 | app2 "youzoo/why/pkg/app"
7 | "youzoo/why/pkg/crypto"
8 | "youzoo/why/pkg/storage"
9 | )
10 |
11 | // POST /app/new
12 | func AppNew(ctx iris.Context) {
13 | var app app2.App
14 | err := ctx.ReadJSON(&app)
15 | app.Appid = uuid.New()
16 | if ErrorHandling(err, ctx) {
17 | return
18 | }
19 | // create AppTable
20 | err = storage.CreateApp(app, db)
21 | pri, pub := crypto.GenerateKeyPair(2048)
22 | _ = storage.NewKeyPair(app, string(crypto.PublicKeyToBytes(pub)[:]), string(crypto.PrivateKeyToBytes(pri)[:]), db)
23 | if ErrorHandling(err, ctx) {
24 | return
25 | }
26 | _, _ = ctx.WriteString(app.Dumps())
27 | return
28 | }
29 |
30 | // POST /app/update
31 | func AppUpdate(ctx iris.Context) {
32 | var app app2.App
33 | err := ctx.ReadJSON(&app)
34 | if ErrorHandling(err, ctx) {
35 | return
36 | }
37 | // update AppTable
38 | err = storage.UpdateApp(app, db)
39 | if ErrorHandling(err, ctx) {
40 | return
41 | }
42 | _, _ = ctx.WriteString(app.Dumps())
43 | }
44 |
45 | // GET /app/{appid}
46 | func AppFind(ctx iris.Context) {
47 | appid := ctx.Params().Get("appid")
48 | // find AppTable
49 | app, err := storage.FindApp(appid, db)
50 | if ErrorHandling(err, ctx) {
51 | return
52 | }
53 | _, _ = ctx.JSON(app)
54 | }
55 |
56 | // GET /app/list?from=&count=
57 | func AppList(ctx iris.Context) {
58 | from := ctx.URLParamIntDefault("from", 0)
59 | count := ctx.URLParamIntDefault("count", 50)
60 | // search AppTable
61 | apps, err := storage.ListApp(from, count, db)
62 | if ErrorHandling(err, ctx) {
63 | return
64 | }
65 | _, _ = ctx.JSON(apps)
66 | }
67 |
--------------------------------------------------------------------------------
/pkg/web/build.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "github.com/kataras/iris"
5 | "youzoo/why/pkg/storage"
6 | )
7 |
8 | // POST /build/new
9 | func BuildNew(ctx iris.Context) {
10 | var buildTable storage.BuildTable
11 | err := ctx.ReadJSON(&buildTable)
12 | if ErrorHandling(err, ctx) {
13 | return
14 | }
15 | // create AppTable
16 | build, err := storage.CreateBuild(buildTable, db)
17 | if ErrorHandling(err, ctx) {
18 | return
19 | }
20 | _, _ = ctx.JSON(build)
21 | return
22 | }
23 |
24 | // POST /build/status/set
25 | func BuildStatusSet(ctx iris.Context) {
26 | var buildStatusJson storage.BuildStatusJson
27 | err := ctx.ReadJSON(&buildStatusJson)
28 | if ErrorHandling(err, ctx) {
29 | return
30 | }
31 | // update AppTable
32 | buildTable, err := storage.SetBuildStatus(buildStatusJson, db)
33 | if ErrorHandling(err, ctx) {
34 | return
35 | }
36 | _, _ = ctx.JSON(buildTable)
37 | }
38 |
39 | // GET /build/status/get/{buildID}
40 | func BuildStatusGet(ctx iris.Context) {
41 | buildId := ctx.Params().GetIntDefault("buildID", 0)
42 | if ErrorHandling(err, ctx) {
43 | return
44 | }
45 | // update AppTable
46 | buildTable, err := storage.GetBuildStatus(buildId, db)
47 | if ErrorHandling(err, ctx) {
48 | return
49 | }
50 | _, _ = ctx.JSON(buildTable)
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/web/key.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "github.com/kataras/iris"
5 | app2 "youzoo/why/pkg/app"
6 | "youzoo/why/pkg/storage"
7 | )
8 |
9 | // POST /key/update
10 | func KeyUpdate(ctx iris.Context) {
11 | var app app2.App
12 | err := ctx.ReadJSON(&app)
13 | if ErrorHandling(err, ctx) {
14 | return
15 | }
16 | // update CryptoTable
17 | err = storage.UpdateApp(app, db)
18 | if ErrorHandling(err, ctx) {
19 | return
20 | }
21 | _, _ = ctx.WriteString(app.Dumps())
22 | }
23 |
24 | // GET /key/{appid}
25 | func KeyFind(ctx iris.Context) {
26 | appid := ctx.Params().Get("appid")
27 | // find CryptoTable
28 | cryptoTable, err := storage.FindKeyPair(appid, db)
29 | if ErrorHandling(err, ctx) {
30 | return
31 | }
32 | _, _ = ctx.JSON(cryptoTable)
33 | }
34 |
35 | // GET /key/pub/{appid}
36 | func KeyFindPub(ctx iris.Context) {
37 | appid := ctx.Params().Get("appid")
38 | // find CryptoTable
39 | cryptoTable, err := storage.FindPubKey(appid, db)
40 | if ErrorHandling(err, ctx) {
41 | return
42 | }
43 | _, _ = ctx.JSON(cryptoTable)
44 | }
45 |
46 | // GET /app/pri/{appid}
47 | func KeyFindPri(ctx iris.Context) {
48 | appid := ctx.Params().Get("appid")
49 | // find CryptoTable
50 | cryptoTable, err := storage.FindPriKey(appid, db)
51 | if ErrorHandling(err, ctx) {
52 | return
53 | }
54 | _, _ = ctx.JSON(cryptoTable)
55 | }
56 |
--------------------------------------------------------------------------------
/pkg/web/web.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "github.com/iris-contrib/middleware/cors"
5 | "github.com/kataras/iris"
6 | "youzoo/why/pkg/storage"
7 | )
8 |
9 | var db, err = storage.OpenDb("/tmp/test.db")
10 |
11 | func StartApi(port string) {
12 | web := iris.Default()
13 | web.Logger().SetLevel("debug")
14 | crs := cors.New(cors.Options{
15 | AllowedOrigins: []string{"*"}, //允许通过的主机名称
16 | AllowCredentials: true,
17 | })
18 | appGroup := web.Party("/app", crs).AllowMethods(iris.MethodOptions)
19 | {
20 | appGroup.Handle("POST", "/new", AppNew)
21 | appGroup.Handle("POST", "/update", AppUpdate)
22 | appGroup.Handle("GET", "/{appid}", AppFind)
23 | appGroup.Handle("GET", "/list", AppList)
24 | }
25 | keyGroup := web.Party("/key", crs).AllowMethods(iris.MethodOptions)
26 | {
27 | keyGroup.Handle("POST", "/update", KeyUpdate)
28 | keyGroup.Handle("GET", "/{appid}", KeyFind)
29 | keyGroup.Handle("GET", "/pub/{appid}", KeyFindPub)
30 | keyGroup.Handle("GET", "/pri/{appid}", KeyFindPri)
31 |
32 | }
33 | alertGroup := web.Party("/alert", crs).AllowMethods(iris.MethodOptions)
34 | {
35 | alertGroup.Handle("POST", "/new", AlertNew)
36 | alertGroup.Handle("POST", "/update", AlertUpdate)
37 | //alert_group.Handle("GET", "/search", AlertSearch)
38 | alertGroup.Handle("GET", "/list", AlertList)
39 | }
40 | buildGroup := web.Party("/build", crs).AllowMethods(iris.MethodOptions)
41 | {
42 | buildGroup.Handle("POST", "/new", BuildNew)
43 | buildGroup.Handle("POST", "/status/set", BuildStatusSet)
44 | buildGroup.Handle("POST", "/status/get/{buildID:int}", BuildStatusGet)
45 | }
46 | _ = web.Run(iris.Addr(port), iris.WithoutServerError(iris.ErrServerClosed))
47 |
48 | }
49 |
50 | func ErrorHandling(err error, ctx iris.Context) bool {
51 | if err != nil {
52 | ctx.StatusCode(iris.StatusBadRequest)
53 | _, _ = ctx.WriteString(err.Error())
54 | return true
55 | }
56 | return false
57 | }
58 |
--------------------------------------------------------------------------------
/test/alert_new.json:
--------------------------------------------------------------------------------
1 | {
2 | "Appid": "679a2d46-8313-48f2-8d4b-915107b78eda",
3 | "Level": "danger",
4 | "Type": "Runtime",
5 | "Info": "dfghiawfiwahevfiaysdvfaw",
6 | "PostContact": "panxt@asdsad.com"
7 | }
8 |
--------------------------------------------------------------------------------
/test/app_new.json:
--------------------------------------------------------------------------------
1 | {"DNS": "10.6.48.128", "ExecInfo": {"AbsPath": "/tmp/test"}}
2 |
--------------------------------------------------------------------------------