├── README.md
├── requirements.txt
└── source
├── command-based
└── main.py
└── menu-based
├── api.py
└── main.py
/README.md:
--------------------------------------------------------------------------------
1 | ## 📱 sms_spoofer ```(ONLY FOR EDUCATIONAL USAGE)```
2 |
3 | this utility allows you to send SMS to any phone number from any name with any content (for example send notification about changed password via SMS)
4 | ([example #1](https://i.imgur.com/SOmATqN.jpg), [example #2](https://i.imgur.com/Ll26s2U.jpg))
5 |
6 | 
7 |
8 | ## installation
9 | windows
10 |
11 | ```
12 | 1) download python 3.10+
13 | 2) download and unpack sms_spoofer.zip
14 |
15 | open terminal in unpacked folder and execute following commands
16 | 3) pip install -r requirements.txt
17 | 4) python source/menu-based/main.py
18 | ```
19 |
20 |
21 |
22 | linux
23 |
24 | ```
25 | $ sudo apt-get install python3 git
26 | $ git clone https://github.com/Defaultik/sms_spoofer
27 | $ cd sms_spoofer
28 | $ pip3 install -r requirements.txt
29 | $ python3 source/menu-based/main.py
30 | ```
31 |
32 |
33 |
34 | macos
35 |
36 | ```
37 | $ brew install python3 git
38 | $ git clone https://github.com/Defaultik/sms_spoofer
39 | $ cd sms_spoofer
40 | $ pip3 install -r requirements.txt
41 | $ python3 source/menu-based/main.py
42 | ```
43 |
44 |
45 |
46 | ## f.a.q
47 | **(?) is this free?**
48 | unfortunately this program is just utility that works on API of big sms gateway, and this gateway takes money from every sms that you send
49 |
50 | **(?) does it support any other languages besides English?**
51 | yes, it is supports unicode so program works in English, Russian, Chinese and other languages
52 |
53 | **(?) can I get a ban?**
54 | yes, your account can get a ban from Vonage if you violate their [terms of use](https://www.vonage.com/legal/communications-apis/terms-of-use/)
55 |
56 | **(?) can I use it on unix-like systems?**
57 | yes you can, the utility is not demanding on the system, and the functions are adapted to another systems
58 |
59 |
60 | ##
61 | **i'll glad to get a star from you ❤️**
62 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | annotated-types==0.7.0
2 | certifi==2025.1.31
3 | cffi==1.17.1
4 | charset-normalizer==3.4.1
5 | cryptography==44.0.1
6 | idna==3.10
7 | pycparser==2.22
8 | pydantic==2.10.6
9 | pydantic_core==2.27.2
10 | PyJWT==2.10.1
11 | requests==2.32.3
12 | typing_extensions==4.12.2
13 | urllib3==2.3.0
14 | vonage==4.4.0
15 | vonage-account==1.1.1
16 | vonage-application==2.0.1
17 | vonage-http-client==1.5.1
18 | vonage-jwt==1.1.5
19 | vonage-messages==1.4.0
20 | vonage-network-auth==1.0.2
21 | vonage-network-number-verification==1.0.2
22 | vonage-network-sim-swap==1.1.2
23 | vonage-number-insight==1.0.6
24 | vonage-numbers==1.0.4
25 | vonage-sms==1.1.5
26 | vonage-subaccounts==1.0.4
27 | vonage-users==1.2.1
28 | vonage-utils==1.1.4
29 | vonage-verify==2.1.0
30 | vonage-verify-legacy==1.0.1
31 | vonage-video==1.2.0
32 | vonage-voice==1.3.0
33 |
--------------------------------------------------------------------------------
/source/command-based/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | import configparser
3 | import argparse
4 | from getpass import getpass
5 |
6 | from vonage import Vonage, Auth
7 | from vonage_sms import SmsMessage, SmsResponse
8 |
9 |
10 | def main():
11 | global config
12 |
13 | parser = argparse.ArgumentParser(prog="SMS Spoofer", description="Fake the sender name and message content")
14 | parser.add_argument("-n", "--number", required=True, help="victim's phone number")
15 | parser.add_argument("-s", "--sender", required=True, help="sender name")
16 | parser.add_argument("-t", "--text", required=True, help="message content")
17 | args = parser.parse_args()
18 |
19 | config = configparser.ConfigParser()
20 | if not os.path.exists("config.ini"):
21 | api_key = input("[!] Enter your Vonage API key: ")
22 | api_secret = getpass("[!] Enter your Vonage API Secret: ")
23 |
24 | config.add_section("api_credentials")
25 |
26 | config.set("api_credentials", "api_key", api_key)
27 | config.set("api_credentials", "api_secret", api_secret)
28 |
29 | with open("config.ini", "w") as config_file:
30 | config.write(config_file)
31 |
32 | config.read("config.ini")
33 |
34 | send_sms(args.number, args.sender, args.text)
35 |
36 |
37 | def send_sms(number, sender, text):
38 | auth = Auth(
39 | api_key=config["api_credentials"]["api_key"],
40 | api_secret=config["api_credentials"]["api_secret"]
41 | )
42 |
43 | client = Vonage(auth=auth)
44 |
45 | message = SmsMessage(to=number, from_=sender, text=text, type="unicode")
46 | response: SmsResponse = client.sms.send(message)
47 |
48 | return response
49 |
50 |
51 | if __name__ == "__main__":
52 | main()
--------------------------------------------------------------------------------
/source/menu-based/api.py:
--------------------------------------------------------------------------------
1 | import os
2 | import configparser
3 |
4 | from vonage import Vonage, Auth
5 | from vonage_sms import SmsMessage, SmsResponse
6 | from vonage_account import Balance
7 |
8 |
9 | def send_sms(number, sender, text):
10 | config = configparser.ConfigParser()
11 | config.read(os.path.join("data", "config.ini"))
12 |
13 | # Transmits user data to send sms
14 | auth = Auth(
15 | api_key=config["api_credentials"]["api_key"],
16 | api_secret=config["api_credentials"]["api_secret"]
17 | )
18 |
19 | client = Vonage(auth=auth)
20 |
21 | message = SmsMessage(to=number, from_=sender, text=text, type="unicode")
22 | response: SmsResponse = client.sms.send(message)
23 |
24 | return response
25 |
26 |
27 | def get_balance():
28 | config = configparser.ConfigParser()
29 | config.read(os.path.join("data", "config.ini"))
30 |
31 | auth = Auth(
32 | api_key=config["api_credentials"]["api_key"],
33 | api_secret=config["api_credentials"]["api_secret"]
34 | )
35 |
36 | client = Vonage(auth=auth)
37 |
38 | balance: Balance = client.account.get_balance()
39 |
40 | return (f'{balance.value:0.2f} EUR')
--------------------------------------------------------------------------------
/source/menu-based/main.py:
--------------------------------------------------------------------------------
1 | import configparser
2 | import os
3 | import csv
4 |
5 | from api import send_sms, get_balance
6 |
7 |
8 | BANNER = r"""
9 | ___ __ __ ___ ___ ___ ___ ___ ___ ___ ___
10 | / __| \/ / __| / __| _ \/ _ \ / _ \| __| __| _ \
11 | \__ \ |\/| \__ \ \__ \ _/ (_) | (_) | _|| _|| /
12 | |___/_| |_|___/ |___/_| \___/ \___/|_| |___|_|_\
13 | """
14 |
15 |
16 | def print_options(*args):
17 | # Print a list of options
18 | for i, name in enumerate(args):
19 | print(f"[{i + 1}]", name)
20 |
21 |
22 | def init():
23 | # Checks if we have all needed files in directory, and if not - creates them;
24 | # Starts program cycle
25 | global config
26 |
27 | config = configparser.ConfigParser()
28 |
29 | if not os.path.exists("data"):
30 | os.makedirs("data")
31 |
32 | contacts_path = os.path.join("data", "contacts.csv")
33 | config_path = os.path.join("data", "config.ini")
34 |
35 | if not os.path.exists(contacts_path):
36 | with open(contacts_path, "w", newline="") as contacts_file:
37 | writer = csv.DictWriter(contacts_file, fieldnames=("name", "phone_number"))
38 | writer.writeheader()
39 |
40 | if not os.path.exists(config_path):
41 | api_key = input("Enter your Vonage API key: ")
42 | api_secret = input("Enter your Vonage API Secret: ")
43 |
44 | config.add_section("api_credentials")
45 | config.set("api_credentials", "api_key", api_key)
46 | config.set("api_credentials", "api_secret", api_secret)
47 |
48 | with open(config_path, "w") as config_file:
49 | config.write(config_file)
50 |
51 | config.read(config_path)
52 |
53 | main()
54 |
55 |
56 | def main():
57 | display_menu()
58 | print(f"Thank you for using!\nfrom https://github.com/Defaultik with <3")
59 |
60 |
61 | def display_menu():
62 | # Main Menu Display
63 | while True:
64 | print("=" * 56)
65 | print(BANNER)
66 | print(f"{" " * 10}Your remaining balance is {get_balance()}")
67 | print("=" * 56)
68 |
69 | print_options("Single", "Multiple", "Contacts", "API Credentials", "Exit")
70 | selected_option = input("Enter number of the task: ")
71 | print("=" * 56)
72 | match selected_option:
73 | case "1":
74 | dial_number()
75 | case "2":
76 | dial_numbers()
77 | case "3":
78 | open_contacts()
79 | case "4":
80 | change_api_credentials()
81 | case "5":
82 | break
83 | case _:
84 | print("ERROR: Invalid option, try again")
85 |
86 |
87 | def dial_number():
88 | # Send SMS to a single number menu
89 | number = input("Victim number: ").replace("+", "").replace("-", "").replace(" ", "") # removing pluses and spaces for VonageAPI that accepts only integer number
90 | sender = input("Sender name: ")
91 | text = input("Text: ")
92 |
93 | send_sms(number, sender, text)
94 | print("\nMessage sent successfully!")
95 |
96 |
97 | def dial_numbers():
98 | # Send SMS to multiple numbers menu
99 | print("How many victims?")
100 | print_options("All of contacts", "Manual", "Back")
101 | selected_option = input("Enter number of the task: ")
102 | print("=" * 56)
103 |
104 | numbers = []
105 | match selected_option:
106 | case "1":
107 | with open(os.path.join("data", "contacts.csv"), "r") as contacts_file:
108 | reader = csv.DictReader(contacts_file)
109 | for row in list(reader):
110 | numbers.append(row["phone_number"])
111 | case "2":
112 | count = int(input("How many numbers do you want to bulk: "))
113 | for i in range(count):
114 | number = input(f"Victim number #{i + 1}: ").replace("+", "").replace("-", "").replace(" ", "")
115 | numbers.append(number)
116 | case "3":
117 | return
118 | case _:
119 | print("ERROR: Invalid option")
120 | return
121 |
122 | print()
123 | sender = input("Sender name: ")
124 | text = input("Text: ")
125 |
126 | for number in numbers:
127 | send_sms(number, sender, text)
128 |
129 |
130 | def open_contacts():
131 | # Contact management (new contacts creation, send to contact sms)
132 | with open(os.path.join("data", "contacts.csv"), "r") as contacts_file:
133 | reader = csv.DictReader(contacts_file)
134 | for i, row in enumerate(reader):
135 | print(f"[{i + 1}]", row["name"])
136 |
137 | print("\n[*] Create a new contact")
138 | print("[X] Back")
139 |
140 | task = input("\nEnter number of the task: ")
141 | print("=" * 56)
142 | match task:
143 | case "*":
144 | new_contact()
145 | case "x" | "X":
146 | return
147 | case _:
148 | try:
149 | select_num = int(task) - 1
150 | with open(os.path.join("data", "contacts.csv"), "r") as contacts_file:
151 | reader = csv.DictReader(contacts_file)
152 | rows = list(reader)
153 |
154 | number = rows[select_num]["phone_number"]
155 | print()
156 | sender = input("Sender name: ")
157 | text = input("Text: ")
158 |
159 | send_sms(number, sender, text)
160 | except (ValueError, IndexError):
161 | print("ERROR: Invalid option")
162 | return
163 |
164 |
165 | def new_contact():
166 | # New contacts creation menu
167 | contact_name = input("\nContact name: ")
168 | contact_number = input("Contact number: ").replace("+", "").replace("-", "").replace(" ", "") # removing pluses and spaces for VonageAPI which accepts only integer number
169 |
170 | with open(os.path.join("data", "contacts.csv"), "a", newline = "") as contacts_file:
171 | writer = csv.DictWriter(contacts_file, fieldnames=("name", "phone_number"))
172 | writer.writerow({"name": contact_name, "phone_number": contact_number})
173 |
174 |
175 | def change_api_credentials():
176 | # Change API credentials menu
177 | sure = input("Are you sure you want to change API Credentials (Y/N): ")
178 | if (sure.lower() == "y"): # did in in .lower() cuz we need to check any 'y' (small and large)
179 | api_key = input("\nEnter your new Vonage API key: ")
180 | api_secret = input("Enter your new Vonage API Secret: ")
181 |
182 | config.set("api_credentials", "api_key", api_key)
183 | config.set("api_credentials", "api_secret", api_secret)
184 |
185 | with open("config.ini", "w") as config_file:
186 | config.write(config_file)
187 |
188 | config.read("config.ini")
189 |
190 |
191 | if __name__ == "__main__":
192 | init()
--------------------------------------------------------------------------------