Didier Stevens

Wednesday 2 July 2025

Quickpost: Doorbell & Condensation

Filed under: Hardware,Quickpost — Didier Stevens @ 0:00

Remember that I broke the filament of the light-bulb in my doorbell?

Turns out there is another advantage to having a light-bulb in your doorbell: it prevents condensation:


Quickpost info

Tuesday 1 July 2025

Overview of Content Published in June

Filed under: Announcement — Didier Stevens @ 0:00
Here is an overview of content I published in June:

Blog posts: SANS ISC Diary entries:

Friday 20 June 2025

Update: teeplus.py Version 0.0.2

Filed under: My Software,Update — Didier Stevens @ 0:00

This update adds option -t: it directs teeplus.py to use the timestamp as filename for saving the incoming bytes.

teeplus_V0_0_2.zip (http)
MD5: 50C60D13D3FC6BD4306D376694D26858
SHA256: 50D7CA7D03BA6E3893DD032228A73618B560C9D81B485DE76FF415332648EC03

Sunday 15 June 2025

New Tool: myipaddress.py

Filed under: Announcement,My Software,Networking — Didier Stevens @ 0:00

This is a new tool that I use for IPv4 operations, like generating a list of CIDRs based on ASNs, checking if IPv4 addresses are members of CIDRs, …

Here is the man page:

Usage: myipaddress.py [options] command ...
IP address tool

Arguments:
@file: process each file listed in the text file specified
wildcards are supported

Source code put in the public domain by Didier Stevens, no Copyright
Use at your own risk
https://DidierStevens.com

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -m, --man             Print manual
  -u, --uniques         Remove duplicates
  -s, --sort            Sort
  -q, --quiet           Quiet
  -o OUTPUT, --output=OUTPUT
                        Output to file (# supported)
  -v, --invert          Invert selection
  -e, --extra           Include extra info

Manual:

4 commands are available: cidr2ip, asn2cidr, ipincidr and aso2cidr.


Command cidr2ip is used to generate IPv4 addresses for the given
CIDRs.

Example: myipaddress.py cidr2ip 192.168.0.0/24 10.10.10.0/30

Option -u (--unique) will remove all duplicates from the generated
list.

Option -s (--sort) will sort the list.


Command asn2cidr is used to generate a list of IPv4 CIDRs for the
given ASNs (autonomous system numbers).

Example: myipaddress.py asn2cidr 100 1234

Output:
100: 12.30.153.0/24 74.123.89.0/24 102.210.158.0/24 192.118.48.0/24
198.180.4.0/22 199.36.118.0/24 199.48.212.0/22 216.225.27.0/24
1234: 132.171.0.0/16 137.96.0.0/16 193.110.32.0/21

Option -q (--quiet) will produce a simple list of CIDRs, nothing more.

Example: myipaddress.py -q asn2cidr 1234

Output:
132.171.0.0/16
137.96.0.0/16
193.110.32.0/21

Option -u (--unique) will remove all duplicates from the generated
list.

This command requires CSV file GeoLite2-ASN-Blocks-IPv4.csv to be
present in the same folder as script myipaddress.py.
See below for more info.


Command ipincidr is used to generate a list of IPv4 addresses for the
text files.

The text files either contain a list of IPv4 addresses or a list of
IPv4 CIDRs (it can actually be a mix of both in the same file).
Then the command will produce a list for the given IPv4 addresses that
are contained in the given CIDRs.
If a line of the text file contains a / character, it is interpreted
as a CIDR, otherwise it is interpreted as a IPv4 address.
CIDRs can also be followed by an ASO with the tab character as
separator.

Example: myipaddress.py ipincidr cidrs.txt ipv4s.txt

Option -v (--inverse) will invert the logic: all given IPv4 addresses
that are NOT contained in the GIVEN CIDRs are listed.


Command aso2cidr is used to generate a list of IPv4 CIDRs for the
given ASOs substrings (autonomous system organisations).

Example: myipaddress.py aso2cidr sans-institute

Output:
SANS-INSTITUTE: 66.35.60.0/24 104.193.44.0/24

Example: myipaddress.py aso2cidr sans-institute amadeus

Output:
SANS-INSTITUTE: 66.35.60.0/24 104.193.44.0/24
Amadeus Data Processing GmbH: 82.150.224.0/21 82.150.248.0/23
168.153.3.0/24 168.153.4.0/22 168.153.8.0/23 168.153.32.0/22
168.153.40.0/22 168.153.64.0/22 168.153.96.0/24 168.153.106.0/24
168.153.109.0/24 168.153.110.0/23 168.153.144.0/22 168.153.160.0/22
171.17.128.0/18 171.17.255.0/24 185.165.8.0/23 193.23.186.0/24
193.24.37.0/24 195.27.162.0/23 213.70.140.0/24
Amadeus Soluciones Tecnologicas S.A.: 94.142.200.0/21
Amadeus is an international computer reservations system. A subsidary
is in Bangalore and t: 168.153.1.0/24
Amadeus India Pvt.Ltd.: 202.0.109.0/24
Amadeus India: 203.89.132.0/24

Option -q (--quiet) will produce a simple list of CIDRs, nothing more.

Example: myipaddress.py -q aso2cidr sans-institute

Output:
66.35.60.0/24
104.193.44.0/24

Option -e (--extra) will add the ASO (with tab character as
separator).

Example: myipaddress.py -q -e aso2cidr sans-institute

Output:
66.35.60.0/24   SANS-INSTITUTE
104.193.44.0/24 SANS-INSTITUTE

Option -u (--unique) will remove all duplicates from the generated
list.

This command requires CSV file GeoLite2-ASN-Blocks-IPv4.csv to be
present in the same folder as script myipaddress.py.
See below for more info.


File GeoLite2-ASN-Blocks-IPv4.csv can be obtained for free by creating
an account on maxmind.com and then download database known as:
GeoLite ASN: CSV Format
It's a ZIP file that contains file GeoLite2-ASN-Blocks-IPv4.csv.


myipaddress_V0_0_1.zip (http)
MD5: 839550C3E5C6A07C088D27EFD51BE2F7
SHA256: F4DCF325E578F797B3D15316E797EB359E1DA13255E9644841593A1C1C5A9F54

Saturday 14 June 2025

Update: virustotal-search.py Version 0.1.9

Filed under: My Software,Update — Didier Stevens @ 0:00

I added a quota feature to virustotal-search.py’s -l (–limitrequests) option.

-l is an option to limit the number of requests: you specify the maximum number of requests to make, and virustotal-search.py will stop once that maximum is reached. Remark that virustotal-search.py does 4 hash lookups per requests, thus if your remaining quota for the day is 1000, you can use -l 250 to perform a maximum of requests without exceeding your total quota (250 = 1000 / 4).

With this new version, you can also instruct virustotal-search.py to calculate (via the API) how much remaining quota you have, and use that to decide how much queries to perform. This is done with keyword quota:. The syntax is: -l quota:groupid,maximum,reserve.

groupid is the group ID your account belongs to. For example sans_isc.

maximum is your daily API quota: how many lookups can you do in one day.

And reserve is the number of lookups you want to save: how many lookups should remain when virustotal-search.py has finished.

Let’s try an example: assume you want virustotal-search.py to do as much queries as possible, but leave a reserve of 100 lookups. Option -l will look like this: -l quota:sans_isc,10000,100.

sans_isc is your group ID, 10000 is the daily API quota, 100 is the reserve.

If you want virustotal-search.py to query your remaining quota, without doing any lookups, use string query as reserve. Like this: l quota:sans_isc,10000,query.

In this example, 3896 lookups have been consumed, and that gives 10000 – 3896 = 6104 remaining lookups. To lookup file hashes, that means there are 6104 / 4 = 1526 remaining queries.

Thus in this case, starting virustotal-search.py with option -l quota:sans_isc,10000,0 would be the same as -l 1526. The difference is that in the first case, you don’t have to calculate the value 1526, virustotal-search does this for you.

You can combine this feature with option –sleep to have virustotal-search.py use the remaining lookups at the end of the day.

For example, virustotal-search.py –sleep 01:45:00 -l quota:sans_isc,10000,10 will have virustotal-search.py wait until it’s 01:45:00 (15 minutes before UTC midnight in CEST), then query the amount of remaining lookups, and do the lookups so as not to exceed the quota and to leave 10 lookups available.

virustotal-search_V0_1_9.zip (http)
MD5: 8A8D8C47A02D07AAA36FAB5A8667BC54
SHA256: A6062F7C3D910E8B090DF77C81BBF3A0ADE504A4F0F504325C009D9FC792B266

Friday 13 June 2025

Update: myjson-filter.py Version 0.0.9

Filed under: My Software,Update — Didier Stevens @ 0:00

I added value stdout for option -W.

-W stdout: will write all items to stdout (binary) without any end-of-line.
To include an end-of-line, specify a Python string, like this:
-W stdout:’\n’ this will add a newline to the end of the item
-W stdout:’\r’ this will add a carriage return to the end of the item
-W stdout:’\r\n’ this will add a carriage return and newline to the end of the item

myjson-filter_V0_0_9.zip (http)
MD5: FB913E4530B7F13684A0C30EA04D44D8
SHA256: 087FF53B631A294DC6B0EA125DC711806CA28C1B8FA066C4E9A38C7069F354A6

Thursday 12 June 2025

Update: search-for-compression.py 0.0.5

Filed under: My Software,Update — Didier Stevens @ 8:40

I added option -u (–unique) to remove duplicates to search-for-compressions.py.

Wednesday 11 June 2025

Update: pecheck.py Version 0.7.18

Filed under: My Software,Update — Didier Stevens @ 0:00

This is a bugfix version.

pecheck-v0_7_18.zip (http)
MD5: 813F309837091B2035A18272AE5F053F
SHA256: 2976562A8B12F0CDD3E9DBF56929B391CA73AF91906EABC18E9CD663A17155AD

Tuesday 10 June 2025

My Fridge & My Portable Power Station

Filed under: Hardware — Didier Stevens @ 0:00

You probably heard about the blackout in Spain & Portugal that happened more than a month ago at the time I’m writing this, and is still under investigation to find out the root cause.

It inspired me to do the following test: how long will my fridge run when powered by my power station. I own a portable power station (Ecoflow Delta EU), its batteries have a total capacity of 1260 Wh.

My fridge consumes 1,72W in standby and about 27W when the motor is running. Here is a graph of the power it consumes while running over a period of 24 hours:

On average, it requires 529 Wh per day to run.

So I was thinking, theoretically, it should run a bit more than 2 days (1260 Wh / 529 Wh per day = 2,38 days) when powered by my power station.

In practice, it ran just shy of 24 hours before my power station was depleted:

It consumed 266 Wh. Which is far less then the capacity of the batteries in the power station (1260 Wh).

How can this be explained?

My first idea was maybe it’s because of the inductive load (it’s a motor). The power factor is very low (0.06):

I was thinking: maybe the 230V inverter in my power station is not efficient at handling inductive loads.

So I tried with a pure resistive load (an incandescent light bulb of 60W):

I got 595 Wh. Which is still far less than 1260 Wh.

Then I tried with a fan that requires 21W at a power factor of 0.70:

I got 362 Wh:

I started to reformulate my hypothesis: me it’s not the low power factor that make the inverter inefficient, but maybe it’s inefficient at low power demands.

Because while this fan requires 21W, the power station was displaying 31W :

So I did run the fan again, but now with the resistive heating element powered on, so that it would consume a large amount of power (around 1 kWh, that’s the maximum sustained load my power station can handle):

I got 778 Wh out of it:

So that’s the best my power station can deliver at a maximum sustained load of 1 kWh and a nearly pure resistive power factor of 0.99.

Which is only 62% of the rated battery capacity.

Conclusion: I can power my fridge for 1 day in case of a power outage, which should be ample enough in case of a power outage similar to the Spain & Portugal incident. But it’s far from efficient. Inverters seem to very less efficient at very low loads.

Monday 9 June 2025

Update: pngdump.py Version 0.0.7

Filed under: Beta,My Software,Update — Didier Stevens @ 0:00

This update to pngdump.py adds an index for chunks, and allows for the selection of a chunk via its index.

« Previous PageNext Page »

Blog at WordPress.com.