Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
binwalk
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fact-gitdep
binwalk
Commits
27d1a24b
Commit
27d1a24b
authored
Dec 19, 2013
by
devttys0
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated usage output, small directory restructuring.
parent
b16c8417
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
99 additions
and
250 deletions
+99
-250
binwalk
src/bin/binwalk
+2
-2
__init__.py
src/binwalk/__init__.py
+0
-0
common.py
src/binwalk/common.py
+14
-4
compression.py
src/binwalk/compression.py
+3
-1
config.py
src/binwalk/config.py
+14
-6
extract.conf
src/binwalk/configs/extract.conf
+0
-0
display.py
src/binwalk/display.py
+9
-3
entropy.py
src/binwalk/entropy.py
+9
-3
extractor.py
src/binwalk/extractor.py
+24
-4
maths.py
src/binwalk/maths.py
+0
-219
module.py
src/binwalk/module.py
+2
-1
hashmatch.py
src/binwalk/modules/hashmatch.py
+0
-1
plugin.py
src/binwalk/plugin.py
+22
-6
No files found.
src/bin/binwalk
View file @
27d1a24b
...
...
@@ -9,14 +9,14 @@ def display_status(m):
while
True
:
try
:
raw_input
()
print
(
"Progress:
%.2
f
%%
(
%
d /
%
d)
\n
"
%
(((
float
(
m
.
status
.
completed
)
/
float
(
m
.
status
.
total
))
*
100
),
m
.
status
.
completed
,
m
.
status
.
total
))
sys
.
stderr
.
write
(
"Progress:
%.2
f
%%
(
%
d /
%
d)
\n
\n
"
%
(((
float
(
m
.
status
.
completed
)
/
float
(
m
.
status
.
total
))
*
100
),
m
.
status
.
completed
,
m
.
status
.
total
))
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
def
usage
(
modules
):
print
modules
.
help
(
)
sys
.
stderr
.
write
(
modules
.
help
()
)
sys
.
exit
(
1
)
def
main
():
...
...
src/binwalk/__init__.py
View file @
27d1a24b
This diff is collapsed.
Click to expand it.
src/binwalk/common.py
View file @
27d1a24b
...
...
@@ -35,6 +35,8 @@ def file_size(filename):
fd
=
os
.
open
(
filename
,
os
.
O_RDONLY
)
try
:
return
os
.
lseek
(
fd
,
0
,
os
.
SEEK_END
)
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
raise
Exception
(
"file_size failed to obtain the size of '
%
s':
%
s"
%
(
filename
,
str
(
e
)))
finally
:
...
...
@@ -51,7 +53,9 @@ def str2int(string):
'''
try
:
return
int
(
string
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
return
int
(
string
,
16
)
def
strip_quoted_strings
(
string
):
...
...
@@ -85,7 +89,9 @@ def get_quoted_strings(string):
# double quotes, and this function should ignore those. However, it also means that any
# data between two quoted strings (ex: '"quote 1" non-quoted data "quote 2"') will also be included.
return
re
.
findall
(
r'\"(.*)\"'
,
string
)[
0
]
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
return
''
def
unique_file_name
(
base_name
,
extension
=
''
):
...
...
@@ -159,7 +165,9 @@ class MathExpression(object):
if
expression
:
try
:
self
.
value
=
self
.
evaluate
(
self
.
expression
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
def
evaluate
(
self
,
expr
):
...
...
@@ -230,7 +238,9 @@ class BlockFile(io.FileIO):
try
:
self
.
size
=
file_size
(
fname
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
self
.
size
=
0
if
offset
<
0
:
...
...
src/binwalk/compression.py
View file @
27d1a24b
...
...
@@ -161,7 +161,9 @@ class CompressionEntropyAnalyzer(object):
def
__del__
(
self
):
try
:
self
.
fp
.
close
()
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
def
analyze
(
self
):
...
...
src/binwalk/config.py
View file @
27d1a24b
...
...
@@ -35,12 +35,12 @@ class Config:
o PLUGINS - Path to the plugins directory.
'''
# Release version
VERSION
=
"
1.3.0 bet
a"
VERSION
=
"
2.0.0 alph
a"
# Sub directories
BINWALK_USER_DIR
=
".binwalk"
BINWALK_MAGIC_DIR
=
"magic"
BINWALK_CONFIG_DIR
=
"config"
BINWALK_CONFIG_DIR
=
"config
s
"
BINWALK_PLUGINS_DIR
=
"plugins"
# File names
...
...
@@ -118,7 +118,9 @@ class Config:
if
os
.
path
.
islink
(
root
):
root
=
os
.
path
.
realpath
(
root
)
return
os
.
path
.
dirname
(
os
.
path
.
abspath
(
root
))
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
return
''
def
_get_user_dir
(
self
):
...
...
@@ -128,7 +130,9 @@ class Config:
try
:
# This should work in both Windows and Unix environments
return
os
.
getenv
(
'USERPROFILE'
)
or
os
.
getenv
(
'HOME'
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
return
''
def
_file_path
(
self
,
dirname
,
filename
):
...
...
@@ -143,7 +147,9 @@ class Config:
if
not
os
.
path
.
exists
(
dirname
):
try
:
os
.
makedirs
(
dirname
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
fpath
=
os
.
path
.
join
(
dirname
,
filename
)
...
...
@@ -151,7 +157,9 @@ class Config:
if
not
os
.
path
.
exists
(
fpath
):
try
:
open
(
fpath
,
"w"
)
.
close
()
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
return
fpath
...
...
src/binwalk/config/extract.conf
→
src/binwalk/config
s
/extract.conf
View file @
27d1a24b
File moved
src/binwalk/display.py
View file @
27d1a24b
...
...
@@ -69,10 +69,14 @@ class Display(object):
end
=
len
(
data
[
start
:])
self
.
string_parts
.
append
(
data
[
start
:
end
])
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
try
:
self
.
string_parts
.
append
(
data
[
start
:])
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
return
start
...
...
@@ -123,6 +127,8 @@ class Display(object):
# Get the terminal window width
hw
=
struct
.
unpack
(
'hh'
,
fcntl
.
ioctl
(
1
,
termios
.
TIOCGWINSZ
,
'1234'
))
self
.
SCREEN_WIDTH
=
self
.
HEADER_WIDTH
=
hw
[
1
]
except
Exception
as
e
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
src/binwalk/entropy.py
View file @
27d1a24b
...
...
@@ -185,7 +185,9 @@ class FileEntropy(object):
'''
try
:
self
.
fd
.
close
()
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
def
_read_block
(
self
):
...
...
@@ -288,7 +290,9 @@ class FileEntropy(object):
# This results in a divide by zero if one/all plugins returns PLUGIN_TERMINATE or PLUGIN_NO_DISPLAY,
# or if the file being scanned is a zero-size file.
average
=
float
(
float
(
total
)
/
float
(
len
(
offsets
)))
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
if
self
.
plugins
:
...
...
@@ -372,7 +376,9 @@ class FileEntropy(object):
try
:
if
algorithm
.
lower
()
==
'gzip'
:
algo
=
self
.
gzip
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
return
self
.
_do_analysis
(
algo
)
...
...
src/binwalk/extractor.py
View file @
27d1a24b
...
...
@@ -115,7 +115,9 @@ class Extractor:
r
[
'regex'
]
=
re
.
compile
(
values
[
0
])
r
[
'extension'
]
=
values
[
1
]
r
[
'cmd'
]
=
values
[
2
]
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
:
pass
# Verify that the match string was retrieved.
...
...
@@ -183,6 +185,8 @@ class Extractor:
with
open
(
fname
,
'r'
)
as
f
:
for
rule
in
f
.
readlines
():
self
.
add_rule
(
rule
.
split
(
self
.
COMMENT_DELIM
,
1
)[
0
])
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
raise
Exception
(
"Extractor.load_from_file failed to load file '
%
s':
%
s"
%
(
fname
,
str
(
e
)))
...
...
@@ -201,6 +205,8 @@ class Extractor:
for
extract_file
in
extract_files
:
try
:
self
.
load_from_file
(
extract_file
)
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
if
self
.
verbose
:
raise
Exception
(
"Extractor.load_defaults failed to load file '
%
s':
%
s"
%
(
extract_file
,
str
(
e
)))
...
...
@@ -289,7 +295,9 @@ class Extractor:
# Remove the original file that we extracted
try
:
os
.
unlink
(
fname
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
# If the command worked, assume it removed the file extension from the extracted file
...
...
@@ -297,7 +305,9 @@ class Extractor:
if
cleanup_extracted_fname
and
os
.
path
.
exists
(
extracted_fname
)
and
file_size
(
extracted_fname
)
==
0
:
try
:
os
.
unlink
(
extracted_fname
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
# If the command executed OK, don't try any more rules
...
...
@@ -308,7 +318,9 @@ class Extractor:
elif
i
!=
(
len
(
rules
)
-
1
):
try
:
os
.
unlink
(
fname
)
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
# If there was no command to execute, just use the first rule
...
...
@@ -442,6 +454,8 @@ class Extractor:
# Open the output file
try
:
fdout
=
BlockFile
(
fname
,
'w'
)
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
# Fall back to the default name if the requested name fails
fname
=
unique_file_name
(
default_bname
,
extension
)
...
...
@@ -455,6 +469,8 @@ class Extractor:
# Cleanup
fdout
.
close
()
fdin
.
close
()
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
raise
Exception
(
"Extractor.dd failed to extract data from '
%
s' to '
%
s':
%
s"
%
(
file_name
,
fname
,
str
(
e
)))
...
...
@@ -479,6 +495,8 @@ class Extractor:
if
callable
(
cmd
):
try
:
cmd
(
fname
)
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
sys
.
stderr
.
write
(
"WARNING: Extractor.execute failed to run '
%
s':
%
s
\n
"
%
(
str
(
cmd
),
str
(
e
)))
else
:
...
...
@@ -492,6 +510,8 @@ class Extractor:
# Execute.
if
subprocess
.
call
(
shlex
.
split
(
cmd
),
stdout
=
tmp
,
stderr
=
tmp
)
!=
0
:
retval
=
False
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
# Silently ignore no such file or directory errors. Why? Because these will inevitably be raised when
# making the switch to the new firmware mod kit directory structure. We handle this elsewhere, but it's
...
...
src/binwalk/maths.py
deleted
100644 → 0
View file @
b16c8417
#!/usr/bin/env python
# Routines to perform Monte Carlo Pi approximation and Chi Squared tests.
# Used for fingerprinting unknown areas of high entropy (e.g., is this block of high entropy data compressed or encrypted?).
# Inspired by people who actually know what they're doing: http://www.fourmilab.ch/random/
import
math
from
binwalk.compat
import
*
class
MonteCarloPi
(
object
):
'''
Performs a Monte Carlo Pi approximation.
'''
def
__init__
(
self
):
'''
Class constructor.
Returns None.
'''
self
.
reset
()
def
reset
(
self
):
'''
Reset state to the beginning.
'''
self
.
pi
=
0
self
.
error
=
0
self
.
m
=
0
self
.
n
=
0
def
update
(
self
,
data
):
'''
Update the pi approximation with new data.
@data - A string of bytes to update (length must be >= 6).
Returns None.
'''
c
=
0
dlen
=
len
(
data
)
while
(
c
+
6
)
<
dlen
:
# Treat 3 bytes as an x coordinate, the next 3 bytes as a y coordinate.
# Our box is 1x1, so divide by 2^24 to put the x y values inside the box.
x
=
((
ord
(
data
[
c
])
<<
16
)
+
(
ord
(
data
[
c
+
1
])
<<
8
)
+
ord
(
data
[
c
+
2
]))
/
16777216.0
c
+=
3
y
=
((
ord
(
data
[
c
])
<<
16
)
+
(
ord
(
data
[
c
+
1
])
<<
8
)
+
ord
(
data
[
c
+
2
]))
/
16777216.0
c
+=
3
# Does the x,y point lie inside the circle inscribed within our box, with diameter == 1?
if
((
x
**
2
)
+
(
y
**
2
))
<=
1
:
self
.
m
+=
1
self
.
n
+=
1
def
montecarlo
(
self
):
'''
Approximates the value of Pi based on the provided data.
Returns a tuple of (approximated value of pi, percent deviation).
'''
if
self
.
n
:
self
.
pi
=
(
float
(
self
.
m
)
/
float
(
self
.
n
)
*
4.0
)
if
self
.
pi
:
self
.
error
=
math
.
fabs
(
1.0
-
(
math
.
pi
/
self
.
pi
))
*
100.0
return
(
self
.
pi
,
self
.
error
)
else
:
return
(
0.0
,
0.0
)
class
ChiSquare
(
object
):
'''
Performs a Chi Squared test against the provided data.
'''
IDEAL
=
256.0
def
__init__
(
self
):
'''
Class constructor.
Returns None.
'''
self
.
bytes
=
{}
self
.
freedom
=
self
.
IDEAL
-
1
# Initialize the self.bytes dictionary with keys for all possible byte values (0 - 255)
for
i
in
range
(
0
,
int
(
self
.
IDEAL
)):
self
.
bytes
[
chr
(
i
)]
=
0
self
.
reset
()
def
reset
(
self
):
self
.
xc2
=
0.0
self
.
byte_count
=
0
for
key
in
self
.
bytes
.
keys
():
self
.
bytes
[
key
]
=
0
def
update
(
self
,
data
):
'''
Updates the current byte counts with new data.
@data - String of bytes to update.
Returns None.
'''
# Count the number of occurances of each byte value
for
i
in
data
:
self
.
bytes
[
i
]
+=
1
self
.
byte_count
+=
len
(
data
)
def
chisq
(
self
):
'''
Calculate the Chi Square critical value.
Returns the critical value.
'''
expected
=
self
.
byte_count
/
self
.
IDEAL
if
expected
:
for
byte
in
self
.
bytes
.
values
():
self
.
xc2
+=
((
byte
-
expected
)
**
2
)
/
expected
return
self
.
xc2
class
MathAnalyzer
(
object
):
'''
Class wrapper aroung ChiSquare and MonteCarloPi.
Performs analysis and attempts to interpret the results.
'''
# Data blocks must be in multiples of 6 for the monte carlo pi approximation
BLOCK_SIZE
=
32
CHI_CUTOFF
=
512
def
__init__
(
self
,
fp
,
start
,
length
):
'''
Class constructor.
@fp - A seekable, readable, file object that will be the data source.
@start - The start offset to begin analysis at.
@length - The number of bytes to analyze.
Returns None.
'''
self
.
fp
=
fp
self
.
start
=
start
self
.
length
=
length
def
analyze
(
self
):
'''
Perform analysis and interpretation.
Returns a descriptive string containing the results and attempted interpretation.
'''
i
=
0
num_error
=
0
analyzer_results
=
[]
chi
=
ChiSquare
()
self
.
fp
.
seek
(
self
.
start
)
while
i
<
self
.
length
:
rsize
=
self
.
length
-
i
if
rsize
>
self
.
BLOCK_SIZE
:
rsize
=
self
.
BLOCK_SIZE
chi
.
reset
()
chi
.
update
(
self
.
fp
.
read
(
rsize
))
if
chi
.
chisq
()
>=
self
.
CHI_CUTOFF
:
num_error
+=
1
i
+=
rsize
if
num_error
>
0
:
verdict
=
'Low/medium entropy data block'
else
:
verdict
=
'High entropy data block'
result
=
'
%
s,
%
d low entropy blocks'
%
(
verdict
,
num_error
)
return
result
if
__name__
==
"__main__"
:
import
sys
rsize
=
0
largest
=
(
0
,
0
)
num_error
=
0
data
=
open
(
sys
.
argv
[
1
],
'rb'
)
.
read
()
try
:
block_size
=
int
(
sys
.
argv
[
2
],
0
)
except
:
block_size
=
32
chi
=
ChiSquare
()
while
rsize
<
len
(
data
):
chi
.
reset
()
d
=
data
[
rsize
:
rsize
+
block_size
]
if
d
<
block_size
:
break
chi
.
update
(
d
)
if
chi
.
chisq
()
>=
512
:
sys
.
stderr
.
write
(
"0x
%
X ->
%
d
\n
"
%
(
rsize
,
chi
.
xc2
))
num_error
+=
1
if
chi
.
xc2
>=
largest
[
1
]:
largest
=
(
rsize
,
chi
.
xc2
)
rsize
+=
block_size
sys
.
stderr
.
write
(
"Number of deviations:
%
d
\n
"
%
num_error
)
sys
.
stderr
.
write
(
"Largest deviation:
%
d at offset 0x
%
X
\n
"
%
(
largest
[
1
],
largest
[
0
]))
src/binwalk/module.py
View file @
27d1a24b
...
...
@@ -4,6 +4,7 @@ import sys
import
inspect
import
argparse
import
binwalk.common
import
binwalk.config
from
binwalk.compat
import
*
class
ModuleOption
(
object
):
...
...
@@ -380,7 +381,7 @@ class Modules(object):
return
modules
def
help
(
self
):
help_string
=
"
"
help_string
=
"
\n
Binwalk v
%
s
\n
Craig Heffner, http://www.binwalk.org
\n
"
%
binwalk
.
config
.
Config
.
VERSION
for
obj
in
self
.
list
(
attribute
=
"CLI"
):
if
obj
.
CLI
:
...
...
src/binwalk/modules/hashmatch.py
View file @
27d1a24b
...
...
@@ -6,7 +6,6 @@ import ctypes
import
ctypes.util
import
binwalk.common
import
binwalk.module
import
binwalk.smartstrings
from
binwalk.compat
import
*
class
HashResult
(
object
):
...
...
src/binwalk/plugin
s
.py
→
src/binwalk/plugin.py
View file @
27d1a24b
...
...
@@ -115,6 +115,8 @@ class Plugins:
val
=
callback
(
arg
)
if
val
is
not
None
:
retval
|=
val
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
sys
.
stderr
.
write
(
"WARNING:
%
s.
%
s failed:
%
s
\n
"
%
(
callback
.
__module__
,
callback
.
__name__
,
e
))
...
...
@@ -171,7 +173,9 @@ class Plugins:
try
:
enabled
=
plugin_class
.
ENABLED
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
enabled
=
True
plugins
[
key
][
'enabled'
][
module
]
=
enabled
...
...
@@ -180,7 +184,9 @@ class Plugins:
try
:
plugins
[
key
][
'descriptions'
][
module
]
=
plugin_class
.
__doc__
.
strip
()
.
split
(
'
\n
'
)[
0
]
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
plugins
[
key
][
'descriptions'
][
module
]
=
'No description'
return
plugins
...
...
@@ -201,26 +207,36 @@ class Plugins:
# If this plugin is disabled by default and has not been explicitly white listed, ignore it
if
plugin_class
.
ENABLED
==
False
and
module
not
in
self
.
whitelist
:
continue
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
class_instance
=
plugin_class
()
try
:
self
.
result
.
append
(
getattr
(
class_instance
,
self
.
RESULT
))
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
try
:
self
.
pre_scan
.
append
(
getattr
(
class_instance
,
self
.
PRESCAN
))
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
try
:
self
.
post_scan
.
append
(
getattr
(
class_instance
,
self
.
POSTSCAN
))
except
:
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
pass
except
KeyboardInterrupt
as
e
:
raise
e
except
Exception
as
e
:
sys
.
stderr
.
write
(
"WARNING: Failed to load plugin module '
%
s':
%
s
\n
"
%
(
module
,
str
(
e
)))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment