mirror of
https://github.com/apsdehal/awesome-ctf
synced 2024-11-28 21:00:20 +00:00
Remove all the files except README
This commit is contained in:
parent
e72ba89197
commit
621fb77b02
16 changed files with 0 additions and 893 deletions
Binary file not shown.
Binary file not shown.
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 hellman ( hellman1908@gmail.com )
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,109 +0,0 @@
|
|||
xortool.py
|
||||
====================
|
||||
|
||||
A tool to do some xor analysis:
|
||||
|
||||
- guess the key length (based on count of equal chars)
|
||||
- guess the key (base on knowledge of most frequent char)
|
||||
|
||||
Usage
|
||||
---------------------
|
||||
|
||||
! *python3 is not supported, use python 2.x*
|
||||
|
||||
```
|
||||
xortool [-h|--help] [OPTIONS] [<filename>]
|
||||
Options:
|
||||
-l,--key-length length of the key (integer)
|
||||
-c,--char most possible char (one char or hex code)
|
||||
-m,--max-keylen=32 maximum key length to probe (integer)
|
||||
-x,--hex input is hex-encoded str
|
||||
-b,--brute-chars brute-force all possible characters
|
||||
-o,--brute-printable same as -b but will only use printable
|
||||
characters for keys
|
||||
```
|
||||
|
||||
Example
|
||||
---------------------
|
||||
|
||||
```bash
|
||||
# xor is xortool/xortool-xor
|
||||
tests $ xor -f /bin/ls -s "secret_key" > binary_xored
|
||||
|
||||
tests $ xortool binary_xored
|
||||
The most probable key lengths:
|
||||
2: 5.0%
|
||||
5: 8.7%
|
||||
8: 4.9%
|
||||
10: 15.4%
|
||||
12: 4.8%
|
||||
15: 8.5%
|
||||
18: 4.8%
|
||||
20: 15.1%
|
||||
25: 8.4%
|
||||
30: 14.9%
|
||||
Key-length can be 5*n
|
||||
Most possible char is needed to guess the key!
|
||||
|
||||
# 00 is the most frequent byte in binaries
|
||||
tests $ xortool binary_xored -l 10 -c 00
|
||||
...
|
||||
1 possible key(s) of length 10:
|
||||
secret_key
|
||||
|
||||
# decrypted ciphertexts are placed in ./xortool_out/Number_<key repr>
|
||||
# ( have no better idea )
|
||||
tests $ md5sum xortool_out/0_secret_key /bin/ls
|
||||
29942e290876703169e1b614d0b4340a xortool_out/0_secret_key
|
||||
29942e290876703169e1b614d0b4340a /bin/ls
|
||||
```
|
||||
|
||||
The most common use is to pass just the encrypted file and the most frequent character (usually 00 for binaries and 20 for text files) - length will be automatically chosen:
|
||||
|
||||
```bash
|
||||
tests $ xortool tool_xored -c 20
|
||||
The most probable key lengths:
|
||||
2: 5.6%
|
||||
5: 7.8%
|
||||
8: 6.0%
|
||||
10: 11.7%
|
||||
12: 5.6%
|
||||
15: 7.6%
|
||||
20: 19.8%
|
||||
25: 7.8%
|
||||
28: 5.7%
|
||||
30: 11.4%
|
||||
Key-length can be 5*n
|
||||
1 possible key(s) of length 20:
|
||||
an0ther s3cret \xdd key
|
||||
```
|
||||
|
||||
Here, the key is longer then default 32 limit:
|
||||
|
||||
```bash
|
||||
tests $ xortool ls_xored -c 00 -m 64
|
||||
The most probable key lengths:
|
||||
3: 3.3%
|
||||
6: 3.3%
|
||||
9: 3.3%
|
||||
11: 7.0%
|
||||
22: 6.9%
|
||||
24: 3.3%
|
||||
27: 3.2%
|
||||
33: 18.4%
|
||||
44: 6.8%
|
||||
55: 6.7%
|
||||
Key-length can be 3*n
|
||||
1 possible key(s) of length 33:
|
||||
really long s3cr3t k3y... PADDING
|
||||
```
|
||||
|
||||
So, if automated decryption fails, you can calibrate:
|
||||
|
||||
- (`-m`) max length to try longer keys
|
||||
- (`-l`) selected length to see some interesting keys
|
||||
- (`-c`) the most frequent char to produce right plaintext
|
||||
|
||||
Author: hellman ( hellman1908@gmail.com )
|
||||
|
||||
License: MIT License (opensource.org/licenses/MIT)
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
import xortool
|
||||
|
||||
setup(name='xortool',
|
||||
version=xortool.__version__,
|
||||
|
||||
author='hellman',
|
||||
author_email='hellman1908@gmail.com',
|
||||
license="MIT",
|
||||
|
||||
url='https://github.com/hellman/xortool',
|
||||
description='Tool for xor cipher analysis',
|
||||
long_description=open("README.md").read(), # not in rst, but something
|
||||
keywords="xor xortool analysis",
|
||||
|
||||
packages=['xortool'],
|
||||
provides=['xortool'],
|
||||
install_requires=['docopt>=0.6.1'],
|
||||
scripts=["xortool/xortool", "xortool/xortool-xor"],
|
||||
|
||||
classifiers=['Development Status :: 4 - Beta',
|
||||
'Intended Audience :: Science/Research',
|
||||
'Intended Audience :: Information Technology',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 2',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Topic :: Scientific/Engineering :: Mathematics',
|
||||
'Topic :: Security :: Cryptography',
|
||||
],
|
||||
)
|
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
ラ込マ<EFBFBD>瞹悴采<EFBFBD>ニミゥテ檮ォハヘマ<EFBFBD>ロ擡フラ<EFBFBD>ヤ棘サ゚ヌマキテンウンメ巻ネ怜ラ込マ<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>督<EFBFBD>灘ヤ<EFBFBD>そヘ崛タホユ<EFBFBD>糟゚郞奈蕫鈷<EFBFBD>怕ユ巐<EFBFBD><EFBFBD>レ攴ンホ堪洞蜉ナラ<EFBFBD>ヒムΥツノ<EFBFBD>ハ档ギハマスツミ崛トミ<EFBFBD>ルヨュネ檮ォハヘマゥナラ幻桜ネウ罪仭゚ロマアヒ積<EFBFBD><EFBFBD>メ漢゙ロ蟲フユ<EFBFBD>゙ヒ攴彩<EFBFBD>ル檮ォハヘマァツヒマャネホャル梹ャネ栫アル档ギハ桓斎堪ネ積<EFBFBD>蒭マァツヒマスフミマクトニマアテロ螻ヒ椦カネヘ<EFBFBD>マヒ渥ぴ<EFBFBD>トハ蒔トム<EFBFBD>桜ネイチ梃サ゚ハ執テメ<EFBFBD>マロマケチ゚<EFBFBD>ルムマャネン換ロロマソ歳蒔ホヨチヤァ<EFBFBD><EFBFBD>ルヨ堪栽ォ゚ン<EFBFBD>ツリマキテリャタ゚峭ツミマソマム坎剤垰゙梟ュ彩<EFBFBD>歳擲マメ患載蒔フ檮ゾロマアヒ椦カネエィ煽棔ャツヤ歓ル積<EFBFBD><EFBFBD>堪ネ梟ュ罪<EFBFBD>ネ゚悸彩<EFBFBD>リヘ<EFBFBD>楨ク<EFBFBD>トミ崕゚リ漆ネ梹ィフラαマメ<EFBFBD>フハ袂込マ<EFBFBD>込マカルハ滉q愕リフ現レ゚攴τ攣ま垰ララΥフ大ヤ苙亞リメ<EFBFBD>フホ洳ネン<EFBFBD>ルロマキル棘サ゚ヌマウリン<EFBFBD>トリマァツヒマスツヒ<EFBFBD>妻堪トリ<EFBFBD>ルヨ<EFBFBD>ンフシチロ<EFBFBD>レ゚慟テム<EFBFBD>゚ロ浤゚ハ桓剤敢ツフ<EFBFBD>マヌマイツム┨テルマェナフォハヨマェナロマコフハ湿フヘ嬉刷敢ツフ<EFBFBD>゚ロ浤゚ハ<EFBFBD>ハエ<EFBFBD>マヒ<EFBFBD>ンメ漢゙ロマスナロ厳彩<EFBFBD>鮭ョ渚ヘ<EFBFBD>ホロマキル梛ギン坏゙ロ<EFBFBD>フメ愕罪マイツハマアヒエ洳ツワ<EFBFBD>タ゚峭ホ棡キルヒ蒔トム<EFBFBD>Χ袂モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ態ァ孖ィネフ<EFBFBD>ヤ<EFBFBD><EFBFBD>槐ロハ<EFBFBD><EFBFBD>ナ<EFBFBD>エ蜈鵠ナロ椪イツヘ<EFBFBD>ハ棡カフフ桓采唆ネン岶細<EFBFBD>゙ハ蒔トン軸チヌマイトミ┰ノ檮キテ゚攅ネヘマウツヘ<EFBFBD>ツリマェナロ<EFBFBD>込マ<EFBFBD>込峭タロ<EFBFBD>チロ室゙椦ア在攸゙ヨ姦載址トミ<EFBFBD>ルヨ<EFBFBD>ノメョネミヌ<EFBFBD>槃摸フ<EFBFBD>ルムマクトニチヤァ袞<EFBFBD>耘<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鉙<EFBFBD>ホム興細<EFBFBD>テム<EFBFBD>寢マシトハマスチロ鴫<EFBFBD>マ看ラ<EFBFBD>トヘマケネハ峭テルマュチム亟ヤ梔キユロ欽込マ<EFBFBD>込マシリハマサユホ歓ル梟ーホムぐフハ<EFBFBD>チロマスナ゚∋ネヘマアテ樂鼾ワ<EFBFBD>歳αルリャタヘマイトユ<EFBFBD><EFBFBD>涕フ仙ヤ<EFBFBD>マ<EFBFBD>槃看ロマョ゚ロ弦゙ラー采<EFBFBD>ルヨ<EFBFBD>ヘヘ<EFBFBD>ナメネ<EFBFBD>フミ虞ツフマセフヘ<EFBFBD>ナメネ<EFBFBD>ヒヒ⊃ルラー載<EFBFBD>テム<EFBFBD>゙ロ患ァ槃<EFBFBD>込マ<EFBFBD>ルムマシネ椦カネ檮ザハチヤァ袞<EFBFBD><EFBFBD>マ<EFBFBD>簟マ墜ミ圜◇峺ネフ<EFBFBD>゙ヨォチレマシネ梹<EFBFBD>レ゚<EFBFBD>ルムマョ゚ロ匳テハマコネリ<EFBFBD>トミ<EFBFBD>ルヨ<EFBFBD>゙ヌぞツメ<EFBFBD>込マ<EFBFBD>込。<EFBFBD><EFBFBD><EFBFBD>發滸梟ー彩<EFBFBD>高<EFBFBD>テヒ列チラすルヘチカ到<EFBFBD>フレ堪菜<EFBFBD>ネ積<EFBFBD>菻マケチラ鎖細嶽込マ<EFBFBD>込マギ梛サヒラ⊇ノ梟ー高浤゙ラ暦<EFBFBD><EFBFBD>ωム<EFBFBD>レヨ<EFBFBD>ナ桙ォ゙ハマーツハマウフユ<EFBFBD>ルヨ<EFBFBD>ツハ<EFBFBD>゚エマ<EFBFBD>込マ<EFBFBD>栽無マムΟ細<EFBFBD>待<EFBFBD>リニタイトモ<EFBFBD>゙睡熏゚卅トメ湿チロチヤ込マ<EFBFBD>込マ<EFBFBD><EFBFBD>イトワ佼怺゚Ιエエ<EFBFBD>鵠イ<EFBFBD>碕<EFBFBD>犀<EFBFBD>タ宕サネロマセパさフ厮クリミ謙トム<EFBFBD>ハラ匳゙椈ャツミ<EFBFBD>゚ロ忰チハ<EFBFBD><EFBFBD><EFBFBD>チロ鹿ル梔ア゚エマ<EFBFBD>込マ<EFBFBD>酷゚<EFBFBD>涼ヤァ袞<EFBFBD><EFBFBD>マ<EFBFBD><EFBFBD><EFBFBD>チラ叉ラ棺ネ桴ュポ<EFBFBD>萱沖テン峭ツミマケトネ姦宰擲テルマャネヘ坿ルヘマクツフ<EFBFBD>込マ<EFBFBD>込<EFBFBD>テ宕ールロ握フメマュネンーノ棔ソ゚゚そルロ擯Χ蜈込ナロ楙サロロ攸チ槁ウツヘ帋<EFBFBD>験チメ蒔トム<EFBFBD>゙ホ歓トリ<EFBFBD>フハ<EFBFBD>テヘマソ゚ロマシ゚ム┰テ積<EFBFBD><EFBFBD><EFBFBD>ホム興宰<EFBFBD>ホヨ<EFBFBD>込マ<EFBFBD>込<EFBFBD>在址゚ロ↑チヌマェナロ攴細<EFBFBD>トミマウツヘ<EFBFBD>ポ惱゙梟ーナロ攅ルロ<EFBFBD>ヒフウ彩<EFBFBD>采攅ハラ<EFBFBD>フメ<EFBFBD>込マ<EFBFBD>込辞ルヨャ獄<EFBFBD>在鹿ネ椦カネフ<EFBFBD>トヘマソ柵ャ<EFBFBD><EFBFBD>廷<EFBFBD><EFBFBD>゙ホ歓トリ<EFBFBD>フハ<EFBFBD>テ梟ー彩<EFBFBD>犀スフメ間込マ<EFBFBD>込マクトメ机采<EFBFBD>トヘマコネリ<EFBFBD>ネレマォ゙ラ∋彩<EFBFBD>載敢フヒΜ獄<EFBFBD>細愕怺ル<EFBFBD>癪<EFBFBD>ラ<EFBFBD>トミ鹸リレ桓ю袂込マ<EFBFBD>込マ療梹ーヤ梃ゾロマゥネ梹ャネ桙ギヘ<EFBFBD>ハ梟ーヒム攀フハ<EFBFBD>テ椦ア在ャ゚ロ謙彩<EFBFBD>栽渊ホラ温ポ峭ツミチヤ込マ<EFBFBD>込マ陵椁アリ梔キテレマェナロマュンロ弦ヒラ諺ルラー菜ャ塞ォ゚档ソテル堊ハロマシネ梔ソリメ岌歳<EFBFBD>フヘ間込マ<EFBFBD>込マュネミ<EFBFBD>フ椌サンム擡宰<EFBFBD>ナ梟ー゙ハ抬ホハ<EFBFBD>テ梳ー宰<EFBFBD>ル椦ア菜<EFBFBD><EFBFBD>マ<EFBFBD>ヒマコツミネェ斎耳ネ椦アァ槃<EFBFBD>込マ<EFBFBD>ヒラ<EFBFBD>ルヨ<EFBFBD>゙ホ歓トリ<EFBFBD>フハ<EFBFBD>テ椁アリフ惱チリチヤァ槃<EFBFBD>込マ<EFBFBD><EFBFBD><EFBFBD>レ゚<EFBFBD>トハマクトミ軸チヌマュナム坿ノ档アツユマイトユ<EFBFBD><EFBFBD><EFBFBD>ルヨ<EFBFBD>ハロ⊇゚ラ<EFBFBD>゙ホ歓トリ<EFBFBD>フハ<EFBFBD>テエマ<EFBFBD>込マ<EFBFBD>細<EFBFBD>テム<EFBFBD>ホム擣ネン庠在鴫剤<EFBFBD>゙ロ寛細<EFBFBD>ルヨ<EFBFBD>゙ネー崎梔キチロチ<EFBFBD>搾垤ルロマソ菜勧在<EFBFBD>テル姦ァ槃<EFBFBD>込マ<EFBFBD>ツミマェツホマアヒ椦カネ梭サテロ攅ホ棡ョネン<EFBFBD>トン蒔トム<EFBFBD>ポ<EFBFBD>マロマウフレ<EFBFBD>レラ峺ツヒ<EFBFBD>ノヒ浚トン蒔トム<EFBFBD>込マ<EFBFBD>込マアヒ椦カネ椈カツメ<EFBFBD><EFBFBD>ー昶<EFBFBD>漱鋧コネヘ軒トホ峭ツミチヤァ袞<EFBFBD><EFBFBD>マ<EFBFBD><EFBFBD>ムそ采<EFBFBD>ルヨ<EFBFBD>ヒヒ⊃ルラー゙椈カトン<EFBFBD>フメ愕斎鴫ノメ桓桜ソィ屓汐ネ梃ォ゚フ寛ルメ<EFBFBD>マフオネミチヤ込マ<EFBFBD>込マ<EFBFBD>ネル<EFBFBD>フミ<EFBFBD>蒡呟犀アニヒ洒采舷フヘ<EFBFBD>テ゚Υヤ梏ソンホ寛宰<EFBFBD>テ栫アル栫サネレ桓<EFBFBD>マ看ラ慟込マ<EFBFBD>込マカフホ渊テヘマキテ梭サル゚脅゚ラ∈ツ免<EFBFBD>フミ<EFBFBD>ハロ峅フモ換テリ<EFBFBD>積<EFBFBD>蒡呟斎鴫ノメ<EFBFBD>ハ梳クァ槃<EFBFBD>込マ<EFBFBD>ルヨ姦ネ梔ォテン峭ツミ<EFBFBD>トヘマ第椦カツヒ宛罪⊆彩<EFBFBD>゚ロマソ゚ロマョフハ幻ネヘマソロ゚<EFBFBD>フワ<EFBFBD>彩<EFBFBD>ヒラ琳込マ<EFBFBD>込マェナロマ<EFBFBD>ネル<EFBFBD>ホム興罪<EFBFBD>レロΥΧ蝣モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蔵モタ蜍チフ<EFBFBD>ナ椨ャネホ渊゚エ峡ネホ渊゚<EFBFBD>攴ノヨ蒔<EFBFBD>ウァ
|
Binary file not shown.
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
__all__ = ["args", "colors", "libcolors", "routine"]
|
||||
__version__ = "0.96"
|
|
@ -1,28 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
from docopt import docopt
|
||||
|
||||
from routine import parse_char
|
||||
|
||||
|
||||
class ArgError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def parse_parameters(doc, version):
|
||||
p = docopt(doc, version=version)
|
||||
p = {k.lstrip("-"): v for k, v in p.items()}
|
||||
try:
|
||||
return {
|
||||
"input_is_hex": bool(p["hex"]),
|
||||
"max_key_length": int(p["max-keylen"]),
|
||||
"known_key_length": int(p["key-length"]) if p["key-length"] else None,
|
||||
"most_frequent_char": parse_char(p["char"]) if p["char"] else None,
|
||||
"brute_chars": bool(p["brute-chars"]),
|
||||
"brute_printable": bool(p["brute-printable"]),
|
||||
"frequency_spread": 0, # to be removed
|
||||
"filename": p["FILE"] if p["FILE"] else "-", # stdin by default
|
||||
}
|
||||
except ValueError as err:
|
||||
raise ArgError(str(err))
|
|
@ -1,19 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
from libcolors import color
|
||||
|
||||
C_RESET = color()
|
||||
C_FATAL = color("red")
|
||||
C_WARN = color("yellow")
|
||||
|
||||
C_KEYLEN = color("green")
|
||||
C_PROB = color("white", attrs="")
|
||||
C_BEST_KEYLEN = color("green", attrs="bold")
|
||||
C_BEST_PROB = color("white", attrs="bold")
|
||||
|
||||
C_DIV = color(attrs="bold")
|
||||
|
||||
C_KEY = color("red", attrs="bold")
|
||||
C_BOLD = color(attrs="bold")
|
||||
C_COUNT = color("yellow", attrs="bold")
|
|
@ -1,80 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
import os
|
||||
|
||||
|
||||
BASH_ATTRIBUTES = {"regular": "0",
|
||||
"bold": "1", "underline": "4", "strike": "9",
|
||||
"light": "1", "dark": "2",
|
||||
"invert": "7"} # invert bg and fg
|
||||
|
||||
BASH_COLORS = {"black": "30", "red": "31", "green": "32", "yellow": "33",
|
||||
"blue": "34", "purple": "35", "cyan": "36", "white": "37"}
|
||||
|
||||
BASH_BGCOLORS = {"black": "40", "red": "41", "green": "42", "yellow": "43",
|
||||
"blue": "44", "purple": "45", "cyan": "46", "white": "47"}
|
||||
|
||||
|
||||
def _main():
|
||||
header = color("white", "black", "dark")
|
||||
print
|
||||
|
||||
print header + " " + "Colors and backgrounds: " + color()
|
||||
for c in _keys_sorted_by_values(BASH_COLORS):
|
||||
c1 = color(c)
|
||||
c2 = color("white" if c != "white" else "black", bgcolor=c)
|
||||
print (c.ljust(10) +
|
||||
c1 + "colored text" + color() + " " +
|
||||
c2 + "background" + color())
|
||||
print
|
||||
|
||||
print header + " " + "Attributes: " + color()
|
||||
for c in _keys_sorted_by_values(BASH_ATTRIBUTES):
|
||||
c1 = color("red", attrs=c)
|
||||
c2 = color("white", attrs=c)
|
||||
print (c.ljust(13) +
|
||||
c1 + "red text" + color() + " " +
|
||||
c2 + "white text" + color())
|
||||
print
|
||||
return
|
||||
|
||||
|
||||
def color(color=None, bgcolor=None, attrs=None):
|
||||
if not is_bash():
|
||||
return ""
|
||||
|
||||
ret = "\x1b[0"
|
||||
if attrs:
|
||||
for attr in attrs.lower().split():
|
||||
attr = attr.strip(",+|")
|
||||
if attr not in BASH_ATTRIBUTES:
|
||||
raise ValueError("Unknown color attribute: " + attr)
|
||||
ret += ";" + BASH_ATTRIBUTES[attr]
|
||||
|
||||
if color:
|
||||
if color in BASH_COLORS:
|
||||
ret += ";" + BASH_COLORS[color]
|
||||
else:
|
||||
raise ValueError("Unknown color: " + color)
|
||||
|
||||
if bgcolor:
|
||||
if bgcolor in BASH_BGCOLORS:
|
||||
ret += ";" + BASH_BGCOLORS[bgcolor]
|
||||
else:
|
||||
raise ValueError("Unknown background color: " + bgcolor)
|
||||
|
||||
return ret + "m"
|
||||
|
||||
|
||||
def is_bash():
|
||||
return os.environ.get("SHELL", "unknown").endswith("bash")
|
||||
|
||||
|
||||
def _keys_sorted_by_values(adict):
|
||||
"""Return list of the keys of @adict sorted by values."""
|
||||
return sorted(adict, key=adict.get)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
|
@ -1,98 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import string
|
||||
|
||||
|
||||
class MkdirError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def load_file(filename):
|
||||
if filename == "-":
|
||||
return sys.stdin.read()
|
||||
fd = open(filename, "rb")
|
||||
contents = fd.read()
|
||||
fd.close()
|
||||
return contents
|
||||
|
||||
|
||||
def save_file(filename, data):
|
||||
fd = open(filename, "wb")
|
||||
fd.write(data)
|
||||
fd.close()
|
||||
return
|
||||
|
||||
|
||||
def mkdir(dirname):
|
||||
if os.path.exists(dirname):
|
||||
return
|
||||
try:
|
||||
os.mkdir(dirname)
|
||||
except BaseException as err:
|
||||
raise MkdirError(str(err))
|
||||
return
|
||||
|
||||
|
||||
def rmdir(dirname):
|
||||
if dirname[-1] == os.sep:
|
||||
dirname = dirname[:-1]
|
||||
if os.path.islink(dirname):
|
||||
return # do not clear link - we can get out of dir
|
||||
files = os.listdir(dirname)
|
||||
for f in files:
|
||||
if f == '.' or f == '..':
|
||||
continue
|
||||
path = dirname + os.sep + f
|
||||
if os.path.isdir(path):
|
||||
rmdir(path)
|
||||
else:
|
||||
os.unlink(path)
|
||||
os.rmdir(dirname)
|
||||
return
|
||||
|
||||
|
||||
def decode_from_hex(text):
|
||||
only_hex_digits = "".join([c for c in text if c in string.hexdigits])
|
||||
return only_hex_digits.decode("hex")
|
||||
|
||||
|
||||
def parse_char(ch):
|
||||
"""
|
||||
'A' or '\x41' or '41'
|
||||
"""
|
||||
if len(ch) == 1:
|
||||
return ord(ch)
|
||||
if ch[0:2] == "\\x":
|
||||
ch = ch[2:]
|
||||
if not ch:
|
||||
raise ValueError("Empty char")
|
||||
return ord(chr(int(ch, 16)))
|
||||
|
||||
|
||||
def dexor(text, key):
|
||||
ret = list(text)
|
||||
mod = len(key)
|
||||
for index, char in enumerate(ret):
|
||||
ret[index] = chr(ord(char) ^ ord(key[index % mod]))
|
||||
return "".join(ret)
|
||||
|
||||
|
||||
def die(exitMessage, exitCode=1):
|
||||
print exitMessage
|
||||
sys.exit(exitCode)
|
||||
|
||||
|
||||
def is_linux():
|
||||
return sys.platform.startswith("linux")
|
||||
|
||||
|
||||
def alphanum(s):
|
||||
lst = list(s)
|
||||
for index, char in enumerate(lst):
|
||||
if char in (string.letters + string.digits):
|
||||
continue
|
||||
lst[index] = char.encode("hex")
|
||||
return "".join(lst)
|
|
@ -1,381 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
"""
|
||||
xortool
|
||||
A tool to do some xor analysis:
|
||||
- guess the key length (based on count of equal chars)
|
||||
- guess the key (base on knowledge of most frequent char)
|
||||
|
||||
Usage:
|
||||
xortool [-x] [-m MAX-LEN] [FILE]
|
||||
xortool [-x] [-l LEN] [-c CHAR | -b | -o] [FILE]
|
||||
xortool [-x] [-m MAX-LEN| -l LEN] [-c CHAR | -b | -o] [FILE]
|
||||
xortool [-h | --help]
|
||||
xortool --version
|
||||
|
||||
Options:
|
||||
-x --hex input is hex-encoded str
|
||||
-l LEN, --key-length=LEN length of the key
|
||||
-m MAX-LEN, --max-keylen=MAX-LEN maximum key length to probe [default: 65]
|
||||
-c CHAR, --char=CHAR most frequent char (one char or hex code)
|
||||
-b --brute-chars brute force all possible most frequent chars
|
||||
-o --brute-printable same as -b but will only check printable chars
|
||||
-h --help show this help
|
||||
|
||||
Examples:
|
||||
xortool file.bin
|
||||
xortool -l 11 -c 20 file.bin
|
||||
xortool -x -c ' ' file.hex
|
||||
"""
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
import os
|
||||
import string
|
||||
import xortool
|
||||
from xortool.colors import *
|
||||
|
||||
from xortool.routine import *
|
||||
from xortool.args import parse_parameters, ArgError
|
||||
|
||||
DIRNAME = 'xortool_out' # here plaintexts will be placed
|
||||
PARAMETERS = dict()
|
||||
|
||||
|
||||
class AnalysisError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
global PARAMETERS
|
||||
try:
|
||||
PARAMETERS = parse_parameters(__doc__, xortool.__version__)
|
||||
ciphertext = get_ciphertext()
|
||||
update_key_length(ciphertext)
|
||||
|
||||
if PARAMETERS["brute_chars"]:
|
||||
try_chars = range(256)
|
||||
elif PARAMETERS["brute_printable"]:
|
||||
try_chars = map(ord, string.printable)
|
||||
elif PARAMETERS["most_frequent_char"] != None:
|
||||
try_chars = [PARAMETERS["most_frequent_char"]]
|
||||
else:
|
||||
die(C_WARN +
|
||||
"Most possible char is needed to guess the key!" +
|
||||
C_RESET)
|
||||
|
||||
(probable_keys,
|
||||
key_char_used) = guess_probable_keys_for_chars(ciphertext, try_chars)
|
||||
|
||||
print_keys(probable_keys)
|
||||
produce_plaintexts(ciphertext, probable_keys, key_char_used)
|
||||
|
||||
except IOError as err:
|
||||
print C_FATAL + "[ERROR] Can't load file:\n\t", err, C_RESET
|
||||
except ArgError as err:
|
||||
print C_FATAL + "[ERROR] Bad argument:\n\t", err, C_RESET
|
||||
except MkdirError as err:
|
||||
print C_FATAL + "[ERROR] Can't create directory:\n\t", err, C_RESET
|
||||
except AnalysisError as err:
|
||||
print C_FATAL + "[ERROR] Analysis error:\n\t", err, C_RESET
|
||||
else:
|
||||
return
|
||||
cleanup()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# LOADING CIPHERTEXT
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def get_ciphertext():
|
||||
"""
|
||||
Load ciphertext from a file or stdin and hex-decode if needed
|
||||
"""
|
||||
ciphertext = load_file(PARAMETERS["filename"])
|
||||
if PARAMETERS["input_is_hex"]:
|
||||
ciphertext = decode_from_hex(ciphertext)
|
||||
return ciphertext
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# KEYLENGTH GUESSING SECTION
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def update_key_length(text):
|
||||
"""
|
||||
Guess length of the key if it's not set. (Updates PARAMETERS)
|
||||
"""
|
||||
global PARAMETERS
|
||||
if PARAMETERS["known_key_length"]:
|
||||
return
|
||||
PARAMETERS["known_key_length"] = guess_key_length(text)
|
||||
return
|
||||
|
||||
|
||||
def guess_key_length(text):
|
||||
"""
|
||||
Try key lengths from 1 to max_key_length and print local maximums.
|
||||
Set key_length to the most possible if it's not set by user.
|
||||
"""
|
||||
fitnesses = calculate_fitnesses(text)
|
||||
if not fitnesses:
|
||||
raise AnalysisError("No candidates for key length found! Too small file?")
|
||||
|
||||
print_fitnesses(fitnesses)
|
||||
guess_and_print_divisors(fitnesses)
|
||||
return get_max_fitnessed_key_length(fitnesses)
|
||||
|
||||
|
||||
def calculate_fitnesses(text):
|
||||
"""
|
||||
Calc. fitnesses for each keylen
|
||||
"""
|
||||
prev = 0
|
||||
pprev = 0
|
||||
fitnesses = []
|
||||
for key_length in range(1, PARAMETERS["max_key_length"] + 1):
|
||||
fitness = count_equals(text, key_length)
|
||||
|
||||
# smaller key-length with nearly the same fitness is preferable
|
||||
fitness = (float(fitness) /
|
||||
(PARAMETERS["max_key_length"] + key_length ** 1.5))
|
||||
|
||||
if pprev < prev and prev > fitness: # local maximum
|
||||
fitnesses += [(key_length - 1, prev)]
|
||||
|
||||
pprev = prev
|
||||
prev = fitness
|
||||
|
||||
if pprev < prev:
|
||||
fitnesses += [(key_length - 1, prev)]
|
||||
|
||||
return fitnesses
|
||||
|
||||
|
||||
def print_fitnesses(fitnesses):
|
||||
print "The most probable key lengths:"
|
||||
|
||||
# top sorted by fitness, but print sorted by length
|
||||
fitnesses.sort(key=itemgetter(1), reverse=True)
|
||||
top10 = fitnesses[:10]
|
||||
best_fitness = top10[0][1]
|
||||
top10.sort(key=itemgetter(0))
|
||||
|
||||
fitness_sum = calculate_fitness_sum(top10)
|
||||
|
||||
for key_length, fitness in top10:
|
||||
s1 = str(key_length).rjust(4, " ")
|
||||
s2 = str(round(100 * fitness * 1.0 / fitness_sum, 1)) + "%"
|
||||
if fitness == best_fitness:
|
||||
print (C_BEST_KEYLEN + s1 + C_RESET + ": "
|
||||
+ C_BEST_PROB + s2 + C_RESET)
|
||||
else:
|
||||
print (C_KEYLEN + s1 + C_RESET + ": "
|
||||
+ C_PROB + s2 + C_RESET)
|
||||
return
|
||||
|
||||
|
||||
def calculate_fitness_sum(fitnesses):
|
||||
return sum([f[1] for f in fitnesses])
|
||||
|
||||
|
||||
def count_equals(text, key_length):
|
||||
"""
|
||||
count equal chars count for each offset and sum them
|
||||
"""
|
||||
equals_count = 0
|
||||
if key_length >= len(text):
|
||||
return 0
|
||||
|
||||
for offset in range(key_length):
|
||||
chars_count = chars_count_at_offset(text, key_length, offset)
|
||||
equals_count += max(chars_count.values()) - 1 # why -1? don't know
|
||||
return equals_count
|
||||
|
||||
|
||||
def guess_and_print_divisors(fitnesses):
|
||||
"""
|
||||
Prints common divisors and returns the most common divisor
|
||||
"""
|
||||
divisors_counts = [0] * (PARAMETERS["max_key_length"] + 1)
|
||||
for key_length, fitness in fitnesses:
|
||||
for number in range(3, key_length + 1):
|
||||
if key_length % number == 0:
|
||||
divisors_counts[number] += 1
|
||||
max_divisors = max(divisors_counts)
|
||||
|
||||
limit = 3
|
||||
ret = 2
|
||||
for number, divisors_count in enumerate(divisors_counts):
|
||||
if divisors_count == max_divisors:
|
||||
print "Key-length can be " + C_DIV + str(number) + "*n" + C_RESET
|
||||
ret = number
|
||||
limit -= 1
|
||||
if limit == 0:
|
||||
return ret
|
||||
return ret
|
||||
|
||||
|
||||
def get_max_fitnessed_key_length(fitnesses):
|
||||
max_fitness = 0
|
||||
max_fitnessed_key_length = 0
|
||||
for key_length, fitness in fitnesses:
|
||||
if fitness > max_fitness:
|
||||
max_fitness = fitness
|
||||
max_fitnessed_key_length = key_length
|
||||
return max_fitnessed_key_length
|
||||
|
||||
|
||||
def chars_count_at_offset(text, key_length, offset):
|
||||
chars_count = dict()
|
||||
for pos in range(offset, len(text), key_length):
|
||||
c = text[pos]
|
||||
if c in chars_count:
|
||||
chars_count[c] += 1
|
||||
else:
|
||||
chars_count[c] = 1
|
||||
return chars_count
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# KEYS GUESSING SECTION
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def guess_probable_keys_for_chars(text, try_chars):
|
||||
"""
|
||||
Guess keys for list of characters.
|
||||
"""
|
||||
probable_keys = []
|
||||
key_char_used = {}
|
||||
|
||||
for c in try_chars:
|
||||
keys = guess_keys(text, c)
|
||||
for key in keys:
|
||||
key_char_used[key] = c
|
||||
if key not in probable_keys:
|
||||
probable_keys.append(key)
|
||||
|
||||
return probable_keys, key_char_used
|
||||
|
||||
|
||||
def guess_keys(text, most_char):
|
||||
"""
|
||||
Generate all possible keys for key length
|
||||
and the most possible char
|
||||
"""
|
||||
key_length = PARAMETERS["known_key_length"]
|
||||
key_possible_bytes = [[] for _ in range(key_length)]
|
||||
|
||||
for offset in range(key_length): # each byte of key<
|
||||
chars_count = chars_count_at_offset(text, key_length, offset)
|
||||
max_count = max(chars_count.values())
|
||||
for char in chars_count:
|
||||
if chars_count[char] >= max_count:
|
||||
key_possible_bytes[offset].append(chr(ord(char) ^ most_char))
|
||||
|
||||
return all_keys(key_possible_bytes)
|
||||
|
||||
|
||||
def all_keys(key_possible_bytes, key_part="", offset=0):
|
||||
"""
|
||||
Produce all combinations of possible key chars
|
||||
"""
|
||||
keys = []
|
||||
if offset >= len(key_possible_bytes):
|
||||
return [key_part]
|
||||
for c in key_possible_bytes[offset]:
|
||||
keys += all_keys(key_possible_bytes, key_part + c, offset + 1)
|
||||
return keys
|
||||
|
||||
|
||||
def print_keys(keys):
|
||||
if not keys:
|
||||
print "No keys guessed!"
|
||||
return
|
||||
|
||||
s1 = C_COUNT + str(len(keys)) + C_RESET
|
||||
s2 = C_COUNT + str(len(keys[0])) + C_RESET
|
||||
print "{} possible key(s) of length {}:".format(s1, s2)
|
||||
for key in keys[:5]:
|
||||
print C_KEY + repr(key)[1:-1] + C_RESET
|
||||
if len(keys) > 10:
|
||||
print "..."
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# RETURNS PERCENTAGE OF PRINTABLE CHARS
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def percentage_printable(text):
|
||||
x = 0.0
|
||||
for c in text:
|
||||
if c in string.printable:
|
||||
x += 1
|
||||
return x / len(text)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# PRODUCE OUTPUT
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def produce_plaintexts(ciphertext, keys, key_char_used):
|
||||
"""
|
||||
Produce plaintext variant for each possible key,
|
||||
creates csv files with keys, percentage of printable
|
||||
characters and used most frequent character
|
||||
"""
|
||||
cleanup()
|
||||
mkdir(DIRNAME)
|
||||
|
||||
# this is split up in two files since the
|
||||
# key can contain all kinds of characters
|
||||
|
||||
fn_key_mapping = "filename-key.csv"
|
||||
fn_perc_mapping = "filename-char_used-perc_printable.csv"
|
||||
|
||||
key_mapping = open(os.path.join(DIRNAME, fn_key_mapping), "w")
|
||||
perc_mapping = open(os.path.join(DIRNAME, fn_perc_mapping), "w")
|
||||
|
||||
key_mapping.write("file_name;key_repr\n")
|
||||
perc_mapping.write("file_name;char_used;perc_printable\n")
|
||||
|
||||
threshold_printable = 95
|
||||
count_printable = 0
|
||||
|
||||
for index, key in enumerate(keys):
|
||||
key_index = str(index).rjust(len(str(len(keys) - 1)), "0")
|
||||
key_repr = repr(key)[1:-1].replace("/", "\\x2f")
|
||||
if not is_linux():
|
||||
key_repr = alphanum(key)
|
||||
file_name = os.path.join(DIRNAME, key_index + ".out")
|
||||
|
||||
dexored = dexor(ciphertext, key)
|
||||
perc = round(100 * percentage_printable(dexored))
|
||||
if perc > threshold_printable:
|
||||
count_printable += 1
|
||||
key_mapping.write("{};{}\n".format(file_name, key_repr))
|
||||
perc_mapping.write("{};{};{}\n".format(file_name,
|
||||
repr(key_char_used[key]),
|
||||
perc))
|
||||
f = open(file_name, "wb")
|
||||
f.write(dexored)
|
||||
f.close()
|
||||
key_mapping.close()
|
||||
perc_mapping.close()
|
||||
|
||||
s1 = C_COUNT + str(count_printable) + C_RESET
|
||||
s2 = C_COUNT + str(round(threshold_printable)) + C_RESET
|
||||
|
||||
print "Found {} plaintexts with {}%+ printable characters".format(s1, s2)
|
||||
print "See files {}, {}".format(fn_key_mapping, fn_perc_mapping)
|
||||
return
|
||||
|
||||
|
||||
def cleanup():
|
||||
if os.path.exists(DIRNAME):
|
||||
rmdir(DIRNAME)
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,116 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#-*- coding:utf-8 -*-
|
||||
|
||||
"""
|
||||
xor strings
|
||||
options:
|
||||
-s - string with \\xAF escapes
|
||||
-r - raw string
|
||||
-h - hex-encoded string (non-letterdigit chars are stripped)
|
||||
-f - read data from file (- for stdin)
|
||||
-n - no newline at the end
|
||||
--no-cycle / --nc - pad smaller strings with null bytes
|
||||
example: xor -s lol -h 414243 -f /etc/passwd
|
||||
|
||||
author: hellman ( hellman1908@gmail.com )
|
||||
"""
|
||||
|
||||
import sys
|
||||
import string
|
||||
import getopt
|
||||
|
||||
|
||||
DATA_OPTS = "s:r:h:f:"
|
||||
HEXES = set("0123456789abcdefABCDEF")
|
||||
|
||||
|
||||
def main():
|
||||
nocycle = False
|
||||
nonewline = False
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "n" + DATA_OPTS, ["no-cycle", "nc"])
|
||||
datas = []
|
||||
for c, val in opts:
|
||||
if c in ("--no-cycle", "--nc"):
|
||||
nocycle = True
|
||||
elif c == "-n":
|
||||
nonewline = True
|
||||
else:
|
||||
v = arg_data(c, val)
|
||||
if v is None:
|
||||
raise getopt.GetoptError("unknown option %s" % c)
|
||||
datas.append(v)
|
||||
if not datas:
|
||||
raise getopt.GetoptError("no data given")
|
||||
except getopt.GetoptError as e:
|
||||
print >>sys.stderr, "error:", e
|
||||
print >>sys.stderr, __doc__
|
||||
quit()
|
||||
|
||||
sys.stdout.write(xor(datas, nocycle=nocycle))
|
||||
if not nonewline:
|
||||
sys.stdout.write("\n")
|
||||
|
||||
|
||||
def xor(args, nocycle=False):
|
||||
maxlen = max(map(len, args))
|
||||
res = [0] * maxlen
|
||||
if nocycle:
|
||||
for s in args:
|
||||
for i in xrange(len(s)):
|
||||
res[i] ^= ord(s[i])
|
||||
else:
|
||||
for s in args:
|
||||
slen = len(s)
|
||||
for i in xrange(maxlen):
|
||||
res[i] ^= ord(s[i % slen])
|
||||
return "".join(map(chr, res))
|
||||
|
||||
|
||||
def from_str(s):
|
||||
res = ""
|
||||
i = 0
|
||||
while True:
|
||||
if i + 4 > len(s):
|
||||
break
|
||||
|
||||
if s[i+1] == "x" and s[i+2] in HEXES and s[i+3] in HEXES:
|
||||
res += chr(int(s[i+2:i+4], 16))
|
||||
i += 4
|
||||
else:
|
||||
res += s[i]
|
||||
i += 1
|
||||
res += s[i:]
|
||||
return res
|
||||
|
||||
|
||||
def from_hex(s):
|
||||
res = ""
|
||||
for c in s:
|
||||
if c in HEXES:
|
||||
res += c
|
||||
elif c in string.ascii_letters:
|
||||
raise ValueError("Bad splitters (alphanum)")
|
||||
return res.decode("hex")
|
||||
|
||||
|
||||
def from_file(s):
|
||||
if s == "-":
|
||||
return sys.stdin.read()
|
||||
return open(s, "rb").read()
|
||||
|
||||
|
||||
def arg_data(opt, s):
|
||||
if opt == "-s":
|
||||
return from_str(s)
|
||||
elif opt == "-r":
|
||||
return s
|
||||
elif opt == "-h":
|
||||
return from_hex(s)
|
||||
elif opt == "-f":
|
||||
return from_file(s)
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in a new issue