ByteWitch's Microscope
  • <script> alert("me"); </script>
  • Vulnerability Analysis
    • Meltdown - How modern CPUs leak sensitive data by side channel attacks
  • Programming
    • Rust: The Greatest Innovation in Modern Programming
  • Concurrency
    • Introduction to Asynchronous Programming
    • Getting started with lock-free concurrent data structure I - Stack
    • Getting started with lock-free concurrent data structure II - Memory ordering and fences
    • Getting started with lock-free concurrent data structure III - Behaviour oriented concurrency
  • Getting started with lock-free concurrent data structure IV - Growable array
  • Getting started with lock-free concurrent data structure V - Split Ordered list (Lock-free Hashmap)
  • Getting started with lock-free concurrent data structure VI - Hazard Pointer
  • Reverse Engineering
    • Code Injection - Python library function hooking
    • Reversing Electron Apps - NodeJS binary modules
  • Native function hooking with Frida
  • Writeups
    • MIT - The missing semester writeup
  • Old-BlogPost
    • Reverse Engineering Techniques - Detect open source Libraries and its functions
    • Analyzing Mi-Home Protocal
    • Modern program and memory structure
    • Finding pointers using Cheat Engine
    • Offsets and how to find them
Powered by GitBook
On this page
  1. Reverse Engineering

Code Injection - Python library function hooking

PreviousGetting started with lock-free concurrent data structure VI - Hazard PointerNextReversing Electron Apps - NodeJS binary modules

Last updated 6 months ago

Today I have a simple task to do, which is download some videos on a website.

The video is in m3u8 format, but it is not a standard m3u8 file. The decryption key and URL is not correct for videos to download or decrypt.

After some reversing of the front-end including debugging with WebAssembly, I figured out the logic of this website.

But what next? Since it is not a standard m3u8, we cannot merge it using FFMpeg. Now a python library come to same us. That is m3u8downloader!

After digging down to its I found out in main.py, the get_url_contentfunction can be modified to replace the path. It returns a bytes object to the caller, which means we can also playing with the data.

So here is what I did, firstly, I imported m3u8downloader.main as a module. Then I backup and modify the function reference to my own function. Just like what frida do!

# HOOK
PARAM="SOME KEY FOR AUTHENTICATION"
_get_url_content = module.get_url_content
def hook(url):
    if "m3u8?" in url:
            return _get_url_content(url)
    if "app.xiaoe-tech.com" in url:
            key1 = list(_get_url_content(url+"SOME OTHER PARAMS"))
            key2 = b'SOMEKEY'
            for i in range(len(key1)):
                key1[i] ^= key2[i]
            return bytes(key1)    
    return _get_url_content(url.replace("ORIGINALURL", "REPLACEMENTURL")+PARAM)
module.get_url_content = hook

After that it works like a charm, however some filename conflict occured when I run this. I found that some .ts file shared the same name but with different url arguments, which has been removed after download. So I hooked another function to make md5 of the url determine the filename.

def get_local_file_for_url(tempdir, url, path_line=None):
    if path_line and path_line.startswith(tempdir):
        return path_line
    return os.path.normpath(os.path.join(tempdir, hashlib.md5(url.encode()).hexdigest()))
module.get_local_file_for_url = get_local_file_for_url

Note that for this purpose I didn't backup the original function. Because we don't have to if we want to implement our own logic. However in most cases, when we want to write a filter, we must backup the original function to call later.

Hope you found this helpful!

source code