├── .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 | 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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
Alert List
IDCreatedAtUpdatedAtAppidLevelTypeInfoPostContact
28 |
29 | 30 | 61 | -------------------------------------------------------------------------------- /frontend/applist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AppList 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
Alert List
AppidDNSAbsPathArgvEnvvPtraceUserName
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 | --------------------------------------------------------------------------------