Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # horrible python garbage written by Jaitsu
- # concept and original C++ implementation credit goes to drgg/Darg
- # i'm sorry mine doesn't have hotkeys, tkinter is pain and so is pynput
- from ctypes import *
- from ctypes.wintypes import *
- from os import system, path
- import sys
- import psutil
- import requests
- SEEDADDRFILE = "noita_seed_address.txt"
- # at time of writing this is the seed address for the october 16th beta
- ADDRESS_MIN = 0x01400000
- ADDRESS_MAX = 0x014DD1E3
- DEFAULTADDR = 0x014DC9E0
- # you need to be admin or have UAC off in order to run this, so let's kill two birds with one stone
- def is_admin():
- try:
- return windll.shell32.IsUserAnAdmin()
- except:
- return False
- if not is_admin():
- print("Not running as admin. Attempting elevation...")
- try:
- windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
- except:
- print()
- print("Can't get admin access. We need that to read Noita's memory for the seed.")
- finally:
- sys.exit()
- # shamelessly ganked from drgg
- matDict = {
- "water": "Water (mat_water)",
- "water_ice": "Chilly Water (mat_water_ice)",
- "water_swamp": "Swamp (mat_water_swamp)",
- "oil": "Oil (mat_oil)",
- "alcohol": "Whiskey (mat_alcohol)",
- "swamp": "Swamp (mat_swamp)",
- "mud": "Mud (mat_mud)",
- "blood": "Blood (mat_blood)",
- "blood_fungi": "Fungus (mat_blood_fungi)",
- "blood_worm": "Worm Blood (mat_blood_worm)",
- "radioactive_liquid": "Toxic Sludge (mat_radioactive_liquid)",
- "cement": "Cement (mat_cement)",
- "acid": "Acid (mat_acid)",
- "lava": "Lava (mat_lava)",
- "urine": "Urine (mat_urine)",
- "poison": "Glowing Liquid (mat_poison)",
- "magic_liquid_teleportation": "Teleportatium (mat_magic_liquid_teleportation)",
- "magic_liquid_polymorph": "Polymorphine (mat_magic_liquid_polymorph)",
- "magic_liquid_random_polymorph": "Chaotic Polymorphine (mat_magic_liquid_random_polymorph)",
- "magic_liquid_berserk": "Berserkium (mat_magic_liquid_berserk)",
- "magic_liquid_charm": "Pheromone (mat_magic_liquid_charm)",
- "magic_liquid_invisibility": "Invisiblium (mat_magic_liquid_invisibility)",
- "sand": "Sand (mat_sand)",
- "bone": "Bone (mat_bone)",
- "soil": "Soil (mat_soil)",
- "honey": "Honey (mat_honey)",
- "slime": "Slime (mat_slime_pink)",
- "snow": "Snow (mat_snow)",
- "rotten_meat": "Rotten Meat (mat_rotten_meat)",
- "wax": "Wax (mat_wax)",
- "gold": "Gold (mat_gold)",
- "silver": "Silver (mat_silver) (UNOBTAINABLE)",
- "copper": "Copper (mat_copper)",
- "brass": "Brass (mat_brass)",
- "diamond": "Diamond (mat_diamond)",
- "coal": "Coal (mat_coal)",
- "gunpowder": "Gunpowder (mat_gunpowder)",
- "gunpowder_explosive": "Gunpowder (mat_gunpowder_explosive)",
- "grass": "Grass (mat_grass)",
- "fungi": "Fungus (mat_fungus)"
- }
- def findSeedAddress(seedtofind):
- # get Noita's process ID
- noitaProcId = 0;
- for proc in psutil.process_iter():
- pinfo = proc.as_dict(attrs=['pid', 'name'])
- if "noita" in pinfo['name'].lower():
- noitaProcId = int(pinfo['pid'])
- if noitaProcId == 0:
- return(-1)
- # okay to preface this I barely have a clue what I'm doing and this might not work properly
- # if the value of the seed you're searching by happens to appear literally anywhere else between
- # ADDRESS_MIN and ADDRESS_MAX but oh well, if it gets the wrong address just restart and try again
- # as long as you're on the same build the address doesn't change
- #
- # in my experience, sometimes the first address is a false positive but it appears twice so taking
- # the second result is your best shot
- PROCESS_ALL_ACCESS = 0x1F0FFF
- buffer = c_char_p(b'0000')
- val = c_int()
- bufferSize = 4
- bytesRead = c_ulong(0)
- addresses = []
- processHandle = windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, noitaProcId)
- for address in range(ADDRESS_MIN, ADDRESS_MAX):
- if windll.kernel32.ReadProcessMemory(processHandle, address, buffer, bufferSize, byref(bytesRead)):
- memmove(ctypes.byref(val), buffer, ctypes.sizeof(val))
- if val.value == seedtofind:
- addresses.append(address)
- else:
- windll.kernel32.CloseHandle(processHandle)
- return(-2)
- if(len(addresses) > 1):
- break
- windll.kernel32.CloseHandle(processHandle)
- if(len(addresses) <= 1):
- return(-3)
- else:
- return(addresses[1])
- def getSeed(address):
- # get Noita's process ID
- noitaProcId = 0;
- for proc in psutil.process_iter():
- pinfo = proc.as_dict(attrs=['pid', 'name'])
- if "noita" in pinfo['name'].lower():
- noitaProcId = int(pinfo['pid'])
- # read the seed from Noita's memory - TODO: find way to dynamically find seed address
- # look I barely comprehend all this I just ganked it from stackoverflow and repurposed it
- PROCESS_ALL_ACCESS = 0x1F0FFF
- buffer = c_char_p(b'0000')
- val = c_int()
- bufferSize = 4
- bytesRead = c_ulong(0)
- processHandle = windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, noitaProcId)
- if windll.kernel32.ReadProcessMemory(processHandle, address, buffer, bufferSize, byref(bytesRead)):
- windll.kernel32.CloseHandle(processHandle)
- memmove(ctypes.byref(val), buffer, ctypes.sizeof(val))
- return(val.value)
- else:
- windll.kernel32.CloseHandle(processHandle)
- return(-1)
- def doSeedCheck(seed):
- if(int(seed) <= 0):
- return("Error: Failed to get seed.")
- resultUrl = "http://94.172.33.134:4921/noita?" + str(seed) + "&hey_you_reading_this_you_will_find_literally_nothing_and_just_waste_your_time"
- response = requests.get(resultUrl)
- if response.status_code != 200:
- return("Error: Server returned status code "+str(response.status_code)+".")
- responseText = response.text
- responseTextStripped = responseText.replace(';',',')
- responseTextSplit = responseTextStripped.split(',')
- msgboxstring = "Seed: "+str(seed)+"\n"\
- +"(If this is wrong, please search for or enter the correct seed address.)"\
- +"\n"\
- +"\n"\
- +"Lively Concoction ("+responseTextSplit[1]+"%):"+"\n"\
- +"\n"\
- +matDict[responseTextSplit[2]]+"\n"\
- +matDict[responseTextSplit[3]]+"\n"\
- +matDict[responseTextSplit[4]]+"\n"\
- +"\n"\
- +"\n"\
- +"Alchemical Precursor ("+responseTextSplit[6]+"%):"+"\n"\
- +"\n"\
- +matDict[responseTextSplit[7]]+"\n"\
- +matDict[responseTextSplit[8]]+"\n"\
- +matDict[responseTextSplit[9]]
- return(msgboxstring)
- def theWholeShebang(seedaddress):
- seed = getSeed(seedaddress)
- message = doSeedCheck(seed)
- system("cls")
- print(message)
- def updateSavedSeedAddr(newseed):
- seedfile = open(SEEDADDRFILE, "w")
- seedfile.write(hex(newseed))
- seedfile.close()
- print("Updated saved seed address: "+hex(newseed))
- ####################################################
- system("cls")
- seedaddress = DEFAULTADDR
- if path.exists(SEEDADDRFILE):
- newseed = 0
- addrfile = open(SEEDADDRFILE, "r")
- try:
- newseedaddr = int(addrfile.readline(), 16)
- seedaddress = newseedaddr
- print("Read seed address from file: "+hex(newseedaddr))
- except:
- print("Error reading seed address file!")
- print("Using default seed address ("+hex(seedaddress)+").")
- finally:
- addrfile.close()
- print()
- print()
- while True:
- print("CURRENT SEED ADDRESS: "+hex(seedaddress))
- print()
- print()
- selection = 0
- presel = input("""Choose from the following:
- 1: Check info for seed (using current address)
- 2: Search for new seed address
- 3: Manually look up a seed
- 4: Enter a new seed address manually
- 5: Exit
- Selection: """)
- try:
- selection = int(presel)
- except:
- pass
- if selection == 1 or presel == "":
- theWholeShebang(seedaddress)
- elif selection < 1 or selection > 5:
- print("Invalid selection.")
- elif selection == 1 or presel == "":
- theWholeShebang(seedaddress)
- elif selection == 2:
- searchseed = int(input("Enter your current seed: "))
- newseedaddr = findSeedAddress(searchseed)
- if newseedaddr == -1:
- print("Couldn't find Noita. Is it running?")
- elif newseedaddr == -2:
- print("An error occurred trying to access Noita's memory.")
- elif newseedaddr == -3:
- print("Could not find the address from that seed.")
- else:
- seedaddress = newseedaddr
- print("Found new seed address at "+hex(seedaddress)+".")
- updateSavedSeedAddr(newseedaddr)
- elif selection == 3:
- manualseed = input("Enter the seed you want to search for: ")
- system("cls")
- print(doSeedCheck(manualseed))
- elif selection == 4:
- manualaddr = int(input("Enter the new address you want to use. (No 0x, just the hex address.): "), base=16)
- if manualaddr < ADDRESS_MIN or manualaddr > ADDRESS_MAX:
- print("Invalid address!")
- print()
- print("(Probably. If you're sure you have the right address,")
- print("edit the Python file and change ADDRESS_MIN/ADDRESS_MAX.)")
- else:
- seedaddress = manualaddr
- updateSavedSeedAddr(manualaddr)
- elif selection == 5:
- print("Goodbye.")
- sys.exit()
- print()
- input("Press Enter to continue.")
- system("cls")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement