📔
Cyber Security Notes
  • Introduction
  • CVEs
    • CVE-2022-33106
  • Paper Reviews
    • Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice
  • Security Basics Notes
    • Identification, Authentication and Authorization
  • Enumeration and Initial Compromise
    • Methodology
    • Footprinting
    • Network Protocols
      • FTP
      • SMB
      • DNS
      • NFS
      • SMTP
      • IMAP/POP3
      • SNMP
      • MySQL
      • MSSQL
      • Oracle TNS
      • IPMI
    • Nifty One Liners
    • Brute-Force Web Pages
      • Hydra
    • Network Pentest
      • Quick SMB cheatsheet
      • SSH keypair basics
      • Compromise using SSH Key
      • Networking fundamentals Interview topics
      • nmap quick cheatsheet
      • Metasploit Quick Reference
    • Web Pentest
      • Web Pentest Interview top topics
      • Wordpress Exploitation
      • Joomla Exploitation
      • Login Bypass using Cookie Tampering/Poisoning
      • Subdomain Enumeration
      • CSRF mitigation
      • XSS mitigation
      • CSP bypass with JSONP
      • PHP Vulnerabilities
      • Python Serialization Vulnerabilities - Pickle
      • SQL Injections
        • SQLmap
      • SSTI
      • XSS
    • Buffer Overflow Prep
      • Understanding CPUs
      • Virtual Memory and Paging
      • Syscalls
      • Theorem Proving
      • Stripping readable function names
      • Insecure C functions
      • Stack Canaries
      • Linking - GOT,PLT
      • Return Oriented Programming
    • Active Directory - Basics
      • AD DS
      • Managing OUs
      • Group Policies
      • Authentications
      • Trees, Forests and Trusts
      • Kerberos
      • Attacking Kerberos
      • Priv Esc (Post Exploitation)
    • DNS/Domain Enum Masterguide
  • Post Exploitation
    • Shell Escape Techniques
    • Getting stable shell after compromise
    • Linux Privilege Escalation
      • Sudoers file
      • Sudoers entry - Yum
      • Wildcards - Basics
      • Wildcards - Chown
      • Wildcards - Tar
      • Linux Permissions & SUID/SGID/Sticky Bit
      • SUID - nmap
      • SUID - bash
      • SUID - man
      • NFS no_root_squash
      • SUID - pkexec
      • Bad permissions
    • Windows Privilege Escalation
      • SeImpersonatePrivilege Token Impersonation
      • Firefox Creds
      • Potatoes
      • Print Spooler Basics
      • Print Spooler CVE 2020-1030
      • SpoolFool
    • Data Exfiltration Post Exploitation
  • Port Forwarding Cheatsheet
  • Powershell Essentials
    • Powershell Basics
    • Powershell Enumeration
    • Powershell Port Scanner
    • Powershell One Liner Port Scanning
    • Powershell Port Scan in a given CIDR
  • Application Security
    • System Calls in Linux
    • Buffer Overflow Defenses
    • Format string vulnerabilities
    • Sample Github Actions
    • Basic Bugs in Demo Application
    • Using AFL++
  • Linux 64-bit Assembly
    • GDB Basics
      • My relevant GDB cheatsheet
      • Task 1 - Tamper strcmp logic
      • Breakpoints
      • Always starting with intel flavor
      • GDB TUI Mode
    • Basic Hello World Program
    • Registers in 64-bit
    • global directive
    • Reducing instructions and Removing NULL-> Optimizing memory in Assembly
    • Data Types
    • Endianness
    • Moving Data
    • push, pop, and the stack
    • Analysis - Writing data on memory location and referencing
    • Arithmetic Operations
    • Bitwise Logical Operations
    • Bit-Shifting Operations
    • Control Instructions
    • Loops
    • Procedures
    • Stack-Frames and Procedures
    • String Operations
    • Shellcoding basics
      • Introduction and Common Rules
      • Basic Shellcodes->Exit
      • Testing shellcode->Skeleton Code
      • Techniques-> JMP,CALL,POP
      • Techniques-> Stack
      • Techniques-> (64-bit only) RIP Relative Addressing
      • Shellcode 1 -> execve(/bin/sh) STACK PUSH
      • Shellcode 1 -> execve(/bin/sh) JMP CALL POP
      • Techniques-> XOR-Encoder
  • Cloud Security
    • Foundational Technology
    • Learning Through Project Omega
    • IAM Essentials
      • Deep dive into IAM - Part 1
    • Amazon S3
    • Risk Management & Data Controls
    • Enumeration
      • S3 - Enum Basics - PwnedLabs
      • S3 - Identify the AWS Account ID from a Public S3 Bucket
      • EBS - Loot Public EBS Volumes
      • S3- Exploit Weak Bucket Policies for Privileged Access
  • API Security
    • WSDL
  • Reverse Engineering
    • Some string Operations
    • Numbers and Inputs
    • Address inputs
    • Recursive Function
    • Crackme: level1
    • Crackme: level2
    • CTF: Memory Dereferencing
    • CTF: Monty Python
  • CTF Challenge Learnings
    • vsCTF 2024
      • Sanity Check
      • not-quite-caesar
      • Intro to reversing
    • NCL Individual 2024
      • Web Challenges
        • PiratePals
        • Pierre's Store
    • Pico CTF 2024
      • Web Exploitation
        • Bookmarklet
        • WebDecode
        • Unminify
        • Trickster
      • General Skills
        • Commitment Issues
        • Time Machine
        • Blame Game
        • Collaborative Development
        • Binary Search
        • Dont-you-love-banners
    • Sunshine CTF
      • Knowledge Repository
    • Amazon WiCys CTF
      • I am Lazy
      • Password Locker on the Web
      • Happy Birthday Card Generator
      • Bloggergate
      • simple offer
      • Bad Actor
      • Secret Server
      • Simple PCAP
      • Hidden Message
    • C code using getenv()
    • Command Injection with filter
    • Pwning
      • Shoddy_CMP
      • PLT_PlayIT
  • Applied Cryptography
    • Linear Congruential Generator
  • Tools for everything
Powered by GitBook
On this page

Was this helpful?

  1. Applied Cryptography

Linear Congruential Generator

LCG is a basic known-seed Pseudo-Random Number Generator which follows this mathematical formula:

Xn+1​=(aXn​+c)modmXn+1​=(aXn​+c)modmXn+1​=(aXn​+c)modm

where:

  • X is the sequence of pseudo-random values,

  • mmm is the modulus,

  • aaa is the multiplier,

  • ccc is the increment,

  • X0X0X0 is the seed or start value.

  • nnn represents the step or position in the sequence of pseudorandom numbers being generated.

  • XnXnXn is the current pseudorandom number at step n.

  • Xn+1Xn+1Xn+1 is the next pseudorandom number in the sequence, generated from Xn.

For example, a=5, c=2, m=123, X0=73

The numbers generated by the formula: will be in the range from 0 to m-1.

The seed value initializes the PRNG's internal state. For an LCG, this is the initial value X0 from which the sequence of pseudorandom numbers begins.

Drawback: The PRNG is deterministic, meaning the sequence it generates is entirely determined by the seed. Even though the numbers appear random, if you know the seed and the algorithm's parameters, you can predict the entire sequence of numbers that will be generated. So, it is not very secure.

Here is a code and description above

"""
-----
Info
-----

This program implements a Linear Congruential Generator which is based on the formula:
Xn+1 = (aXn + c)mod m

My algorithm is designed as follows:
Xn+1 -> is the next pseudorandom number.
Xn -> is the current pseudorandom number (or the seed for the first iteration)
a is the multiplier (in the program, a = 997 which is a large 3 digit priime number)
c is the increment (in the program, c = 1013904223 which is known to generate good combinations of random numbers)
m is the modulus (in the program, m = 2^{32} which a design decision that balances between maintaining some level of quality in the pseudorandom sequence and exploring the effects of changing other parameters.)
If a range to be generated is given, m changes. Otherwise values between 0 to 2^32-1 is generated.
I wanted to test how keeping a as a 3 digit number would react as opposed to the ANSI C standard a=1664525.

---------------
Program Options
---------------

--run: A flag that must be explicitly set to trigger the generation of numbers. Without this flag, the program shows the help message and exits.
	When --run is provided without any other options, default run is done where seed value is the current time and 10 numbers would be generated
	by default between 1 to 100.
-n or --number: Specifies the number of pseudorandom integers to generate. Defaults to 10 if not provided.
--min: The minimum value in the range of generated integers. Defaults to 1.
--max: The maximum value in the range of generated integers. Defaults to 100.
--seed: An optional seed value for the pseudorandom number generator. If not provided, the current time is used as the seed.

------------------------------
Proof of Algorithm - Math used
------------------------------

The code uses timestamp as a seed by default. Let's say you run the code at 2:30 PM on 24th February 2024, EPOCH timestamp is: 1708785000

Q) Generate numbers between 1 and 100, using timestamp 1708785000 and generate 5 numbers:

root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 5 --min 1 --max 100 --seed 1708785000
Generated random integers: [8, 91, 18, 5, 16]
root@hex:/home/hex/cryptography# 

Proof:


The math goes like this:
Formula: Xn+1 = (aXn  +c) mod m
a=997
c= 1013904223
X0= 1708785000
X0+1 = X1 = (997*1708785000 + 1013904223) mod 2^32 = 3865500007

Now we have our first random number 3865500007
But we have to scale this between 1 and 100.

Formula for scaling: 1+(X1 * mod100)

Final X1 = 1+(3865500007mod100) = 8
Similarly, Final X2  = 91
Final X3 = 18
Final X4 = 5
Final X5 = 16

So, we can conclude that the Math algorithm in our program is satisfactory and proves.


--------------------
Test Cases and Usage 
--------------------

To test the program, we take these test cases:
1. Default Execution at present time
2. Execution to generate 10 random numbers in between 1 and 100
3. Execution to generate 5 random numbers (No range)
4. Execution to generate only 1 random number between 1 and 7 (LUCKY 7!!)
5. Execution to generate 2 random numbers between 1 and 6 (Dice roll)


Test Case 1:
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run
Generated random integers: [3885674302, 970682325, 2416540648, 828277223, 2172574722, 2407384873, 289904140, 2285522971, 3347639430, 1420826941]
root@hex:/home/hex/cryptography# 



Test Case 2:
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 10 --min 1 --max 100
Generated random integers: [71, 22, 1, 76, 27, 30, 49, 20, 67, 14]
root@hex:/home/hex/cryptography#


Test Case 3:
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 5
Generated random integers: [3885773005, 1069089216, 1743963167, 283426842, 122624161]
root@hex:/home/hex/cryptography#


Test Case 4:
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [7]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [2]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [5]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [1]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [1]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [4]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [4]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 1 --min 1 --max 7
Generated random integers: [7]
root@hex:/home/hex/cryptography


Test Case 5:
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [3, 2]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [4, 3]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [5, 4]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [6, 5]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [2, 1]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [4, 3]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [6, 5]
root@hex:/home/hex/cryptography# python3 rajpal-lcg.py --run -n 2 --min 1 --max 6
Generated random integers: [2, 1]
root@hex:/home/hex/cryptography#



----------
Conclusion
----------

Upon testing the program and theorem, I concluded that LCG may be effective using large numbers but still is predictable.
Also, when evaluating lucky 7 or dice rolls, consecutive runs were making prediction possible. For example, 3,2 becomes 4,3 the next second then 5,4 the next
So, LCG is not a very effective algorithm for PRNG


"""

import argparse
import time
import sys

class LCG:
    def __init__(self, seed=None):
        self.a = 997
        self.c = 1013904223
        self.m = 2**32
        if seed is None:
            # Use current time as seed if none provided
            self.state = int(time.time())
        else:
            self.state = seed

    def next(self):
        self.state = (self.a * self.state + self.c) % self.m
        return self.state

    def generate_n_integers(self, n=10, min_val=None, max_val=None):
        """
        Generate n integers, either within a given range [min_val, max_val] or in the full range of 0 to m-1 if min_val and max_val are None.
        """
        random_integers = []
        if min_val is None or max_val is None:
            # Generate integers in the full range of 0 to m-1
            for _ in range(n):
                num = self.next()
                random_integers.append(num)
        else:
            # Generate integers within the specified range [min_val, max_val]
            range_width = max_val - min_val + 1
            for _ in range(n):
                num = min_val + (self.next() % range_width)
                random_integers.append(num)
        return random_integers

def main():
    parser = argparse.ArgumentParser(description='Generate pseudorandom integers using a Linear Congruential Generator.')
    parser.add_argument('--run', action='store_true', help='Run the generator in default state and generate 10 numbers. Without this flag, the program will not generate numbers.')
    parser.add_argument('-n', '--number', type=int, default=10, help='Number of random integers to generate')
    parser.add_argument('--min', type=int, default=None, help='Minimum value of the random integers (optional). Default [0 to 2^32 -1]')
    parser.add_argument('--max', type=int, default=None, help='Maximum value of the random integers (optional). Default [0 to 2^32 -1]')
    parser.add_argument('--seed', type=int, default=None, help='Seed value for the pseudorandom number generator (optional). By default, uses current time')

    args = parser.parse_args()

    if not args.run:
        parser.print_help()
        sys.exit(1)

    lcg = LCG(args.seed)
    random_integers = lcg.generate_n_integers(args.number, args.min, args.max)
    print("Generated random integers:", random_integers)

if __name__ == "__main__":
    main()

PreviousApplied CryptographyNextTools for everything

Last updated 1 year ago

Was this helpful?