26 Haziran 2022 Pazar

Python ayrıştırma

Python ayrıştırma - Örnek olarak 2048 oyunu alın

Henrik-Yao 2021-12-14 11:48:01
piton ayrıştırma oyunları örneği

Resim açıklamasını buraya ekleyinBir . arka fon

Birlikte ctf konusu, 2048'i kırarak Oyun bayrak alır
Oyunun kuralları basittir, Aynı yönde hareket etmek için tüm blokları kontrol etmeniz gerekir, İki özdeş sayı kare çarpışır ve toplamlarında birleşir, Her işlemden sonra, rastgele 2 belki 4, Ve sonunda bir “2048” elde edin Oyunun kutusu bir zaferdir.

Resim açıklamasını buraya ekleyin

İki . Takım hazırlığı

1.pyinstxtractor.py Komut dosyaları, python'u geri derlemek için kullanılır

Senaryo şu şekilde


from __future__ import print_function
import os
import struct
import marshal
import zlib
import sys
import imp
import types
from uuid import uuid4 as uniquename
class CTOCEntry:
def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name):
self.position = position
self.cmprsdDataSize = cmprsdDataSize
self.uncmprsdDataSize = uncmprsdDataSize
self.cmprsFlag = cmprsFlag
self.typeCmprsData = typeCmprsData
self.name = name
class PyInstArchive:
PYINST20_COOKIE_SIZE = 24 # For pyinstaller 2.0
PYINST21_COOKIE_SIZE = 24 + 64 # For pyinstaller 2.1+
MAGIC = b'MEI\014\013\012\013\016' # Magic number which identifies pyinstaller
def __init__(self, path):
self.filePath = path
def open(self):
try:
self.fPtr = open(self.filePath, 'rb')
self.fileSize = os.stat(self.filePath).st_size
except:
print('[*] Error: Could not open {0}'.format(self.filePath))
return False
return True
def close(self):
try:
self.fPtr.close()
except:
pass
def checkFile(self):
print('[*] Processing {0}'.format(self.filePath))
# Check if it is a 2.0 archive
self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
magicFromFile = self.fPtr.read(len(self.MAGIC))
if magicFromFile == self.MAGIC:
self.pyinstVer = 20 # pyinstaller 2.0
print('[*] Pyinstaller version: 2.0')
return True
# Check for pyinstaller 2.1+ before bailing out
self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
magicFromFile = self.fPtr.read(len(self.MAGIC))
if magicFromFile == self.MAGIC:
print('[*] Pyinstaller version: 2.1+')
self.pyinstVer = 21 # pyinstaller 2.1+
return True
print('[*] Error : Unsupported pyinstaller version or not a pyinstaller archive')
return False
def getCArchiveInfo(self):
try:
if self.pyinstVer == 20:
self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
# Read CArchive cookie
(magic, lengthofPackage, toc, tocLen, self.pyver) = \
struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE))
elif self.pyinstVer == 21:
self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
# Read CArchive cookie
(magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \
struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE))
except:
print('[*] Error : The file is not a pyinstaller archive')
return False
print('[*] Python version: {0}'.format(self.pyver))
# Overlay is the data appended at the end of the PE
self.overlaySize = lengthofPackage
self.overlayPos = self.fileSize - self.overlaySize
self.tableOfContentsPos = self.overlayPos + toc
self.tableOfContentsSize = tocLen
print('[*] Length of package: {0} bytes'.format(self.overlaySize))
return True
def parseTOC(self):
# Go to the table of contents
self.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET)
self.tocList = []
parsedLen = 0
# Parse table of contents
while parsedLen < self.tableOfContentsSize:
(entrySize, ) = struct.unpack('!i', self.fPtr.read(4))
nameLen = struct.calcsize('!iiiiBc')
(entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \
struct.unpack( \
'!iiiBc{0}s'.format(entrySize - nameLen), \
self.fPtr.read(entrySize - 4))
name = name.decode('utf-8').rstrip('\0')
if len(name) == 0:
name = str(uniquename())
print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name))
self.tocList.append( \
CTOCEntry( \
self.overlayPos + entryPos, \
cmprsdDataSize, \
uncmprsdDataSize, \
cmprsFlag, \
typeCmprsData, \
name \
))
parsedLen += entrySize
print('[*] Found {0} files in CArchive'.format(len(self.tocList)))
def extractFiles(self):
print('[*] Beginning extraction...please standby')
extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted')
if not os.path.exists(extractionDir):
os.mkdir(extractionDir)
os.chdir(extractionDir)
for entry in self.tocList:
basePath = os.path.dirname(entry.name)
if basePath != '':
# Check if path exists, create if not
if not os.path.exists(basePath):
os.makedirs(basePath)
self.fPtr.seek(entry.position, os.SEEK_SET)
data = self.fPtr.read(entry.cmprsdDataSize)
if entry.cmprsFlag == 1:
data = zlib.decompress(data)
# Malware may tamper with the uncompressed size
# Comment out the assertion in such a case
assert len(data) == entry.uncmprsdDataSize # Sanity Check
with open(entry.name, 'wb') as f:
f.write(data)
if entry.typeCmprsData == b's':
print('[+] Possible entry point: {0}'.format(entry.name))
elif entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z':
self._extractPyz(entry.name)
def _extractPyz(self, name):
dirName = name + '_extracted'
# Create a directory for the contents of the pyz
if not os.path.exists(dirName):
os.mkdir(dirName)
with open(name, 'rb') as f:
pyzMagic = f.read(4)
assert pyzMagic == b'PYZ\0' # Sanity Check
pycHeader = f.read(4) # Python magic value
if imp.get_magic() != pycHeader:
print('[!] Warning: The script is running in a different python version than the one used to build the executable')
print(' Run this script in Python{0} to prevent extraction errors(if any) during unmarshalling'.format(self.pyver))
(tocPosition, ) = struct.unpack('!i', f.read(4))
f.seek(tocPosition, os.SEEK_SET)
try:
toc = marshal.load(f)
except:
print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name))
return
print('[*] Found {0} files in PYZ archive'.format(len(toc)))
# From pyinstaller 3.1+ toc is a list of tuples
if type(toc) == list:
toc = dict(toc)
for key in toc.keys():
(ispkg, pos, length) = toc[key]
f.seek(pos, os.SEEK_SET)
fileName = key
try:
# for Python > 3.3 some keys are bytes object some are str object
fileName = key.decode('utf-8')
except:
pass
# Make sure destination directory exists, ensuring we keep inside dirName
destName = os.path.join(dirName, fileName.replace("..", "__"))
destDirName = os.path.dirname(destName)
if not os.path.exists(destDirName):
os.makedirs(destDirName)
try:
data = f.read(length)
data = zlib.decompress(data)
except:
print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(fileName))
open(destName + '.pyc.encrypted', 'wb').write(data)
continue
with open(destName + '.pyc', 'wb') as pycFile:
pycFile.write(pycHeader) # Write pyc magic
pycFile.write(b'\0' * 4) # Write timestamp
if self.pyver >= 33:
pycFile.write(b'\0' * 4) # Size parameter added in Python 3.3
pycFile.write(data)
def main():
if len(sys.argv) < 2:
print('[*] Usage: pyinstxtractor.py <filename>')
else:
arch = PyInstArchive(sys.argv[1])
if arch.open():
if arch.checkFile():
if arch.getCArchiveInfo():
arch.parseTOC()
arch.extractFiles()
arch.close()
print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))
print('')
print('You can now use a python decompiler on the pyc files within the extracted directory')
return
arch.close()
if __name__ == '__main__':
main()
2.winhex 16 İkili Yazılımı düzenlemek için

Sıkıştırılmış paket, blogger kaynağına yüklendi

3、 ... ve . Kaynak koda dönüştürme

1. Komut dosyasını yerleştirin

Komut dosyası ve derlenecek exe Dosyalar aynı yola yerleştirildikten sonra, yol kutusuna girin cmd Terminali açın

Resim açıklamasını buraya ekleyin

2. Komut dosyasını çalıştırın

Python terminaline giriş Bundan sonra, komut dosyası adını ve ayrıştırılacak exe dosya adını girin

Resim açıklamasını buraya ekleyin

Başarılı derlemeden sonra, orijinal yolda aşağıdaki klasörler oluşturulacaktır.

Resim açıklamasını buraya ekleyin

3. Yazılım adını ve dosya yapı dosyasını bulun

Resim açıklamasını buraya ekleyin

4. Winhex Contrast'ı girin

Resim açıklamasını buraya ekleyinResim açıklamasını buraya ekleyin

5. Yapıyı al Bulmacanın önüne fazladan satırı kopyala

Resim açıklamasını buraya ekleyin

6. Son ekini .pyc olarak değiştirin

Resim açıklamasını buraya ekleyin

7. Üçüncü taraf kitaplıklarını derlemeden yükleyin

Resim açıklamasını buraya ekleyin

8.python Versiyonu 3.8 Uncompyle diyebilirsiniz

Karşılık gelen yol terminal girişi uncompyle6 puzzle.pyc > puzzle.py

9.python Sürümü 3.8 Çevrimiçi araçları seçebilirsiniz (.pyc>.py)

https://tool.lu/pyc/

10. Son olarak puzzle.py dosyasını alabiliriz.

Kod aşağıdaki gibidir

#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
import random
from tkinter import Frame, Label, CENTER
import logic
import constants as c
class GameGrid(Frame):
def __init__(self):
Frame.__init__(self)
self.grid()
self.master.title('C1CTF2019')
self.master.bind('<Key>', self.key_down)
self.commands = {

c.KEY_J: logic.down,
c.KEY_K: logic.up,
c.KEY_L: logic.right,
c.KEY_H: logic.left,
c.KEY_RIGHT_ALT: logic.right,
c.KEY_LEFT_ALT: logic.left,
c.KEY_DOWN_ALT: logic.down,
c.KEY_UP_ALT: logic.up,
c.KEY_RIGHT: logic.right,
c.KEY_LEFT: logic.left,
c.KEY_DOWN: logic.down,
c.KEY_UP: logic.up }
self.grid_cells = []
self.init_grid()
self.init_matrix()
self.update_grid_cells()
self.mainloop()
def init_grid(self):
background = Frame(self, c.BACKGROUND_COLOR_GAME, c.SIZE, c.SIZE, **('bg', 'width', 'height'))
background.grid()
for i in range(c.GRID_LEN):
grid_row = []
for j in range(c.GRID_LEN):
cell = Frame(background, c.BACKGROUND_COLOR_CELL_EMPTY, c.SIZE / c.GRID_LEN, c.SIZE / c.GRID_LEN, **('bg', 'width', 'height'))
cell.grid(i, j, c.GRID_PADDING, c.GRID_PADDING, **('row', 'column', 'padx', 'pady'))
t = Label(cell, '', c.BACKGROUND_COLOR_CELL_EMPTY, CENTER, c.FONT, 5, 2, **('master', 'text', 'bg', 'justify', 'font', 'width', 'height'))
t.grid()
grid_row.append(t)
self.grid_cells.append(grid_row)
def gen(self):
return random.randint(0, c.GRID_LEN - 1)
def init_matrix(self):
self.matrix = logic.new_game(4)
self.history_matrixs = list()
self.matrix = logic.add_two(self.matrix)
self.matrix = logic.add_two(self.matrix)
def update_grid_cells(self):
for i in range(c.GRID_LEN):
for j in range(c.GRID_LEN):
new_number = self.matrix[i][j]
if new_number == 0:
self.grid_cells[i][j].configure('', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
continue
self.grid_cells[i][j].configure(str(new_number), c.BACKGROUND_COLOR_DICT[new_number], c.CELL_COLOR_DICT[new_number], **('text', 'bg', 'fg'))
self.update_idletasks()
def key_down(self, event):
key = repr(event.char)
if key == c.KEY_BACK and len(self.history_matrixs) > 1:
self.matrix = self.history_matrixs.pop()
self.update_grid_cells()
print('back on step total step:', len(self.history_matrixs))
elif key in self.commands:
(self.matrix, done) = self.commands[repr(event.char)](self.matrix)
if done:
self.matrix = logic.add_two(self.matrix)
self.history_matrixs.append(self.matrix)
self.update_grid_cells()
done = False
if logic.game_state(self.matrix) == 'win':
self.grid_cells[1][0].configure('C1CTF', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][1].configure('{2048', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][2].configure('_1s_', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][3].configure('fun}', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
if logic.game_state(self.matrix) == 'lose':
self.grid_cells[1][1].configure('You', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][2].configure('Lost!', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
def generate_next(self):
index = (self.gen(), self.gen())
while self.matrix[index[0]][index[1]] != 0:
index = (self.gen(), self.gen())
self.matrix[index[0]][index[1]] = 2
gamegrid = GameGrid()
11. bayrağı bul Büyük duyuru oldu

Resim açıklamasını buraya ekleyin

24 Haziran 2022 Cuma

Autoit A3x Dumper

 



Merhaba arkadaşlar daha önce sizlere duyurduğum Autoit A3x Dumper aracını paylaşıyorum.

A3x formatı kısaca pyc dosya formatına benzer yani okunamaz ama çalıştırıcı tarafından çalıştırılabilirdir.
Mesela siz autoit'de yazdığınız scriptleri derlediğinizde öncelikle sadece derleyicinin anlayacağı formata getirilir yani a3x daha sonra yine normal şifrelenir en son çalıştırıcı programın resource alanına gömülerek derleme işlemi bitirilir.
Ama hafızada çalıştırmak için çözüldüğü ve yorumlayıcıya gönderildiği için rahat şekilde dump edilmesi mümkündür yoksa autoit yorumlayıcısı yazdığınız kodları yorumlayamaz :)





Türkçe :
You must click 'Like' before you can see the hidden data contained here


Kimse belirtmeden ingilizce :
You must click 'Like' before you can see the hidden data contained here


Kullanımı:
You must click 'Like' before you can see the hidden data contained here


Aracın yanında kullanacağınız a3x dosyaları için ek araç:
You must click 'Like' before you can see the hidden data contained here


https://mega.nz/file/T2wAnDYI#JgQpwEdUcKdyqk1Gkt9bdoLLFA8Asydr9xd7SA55hGY


22 Haziran 2022 Çarşamba

GizliDumper by Unlimited

iwdvbs3.jpg
 



Merhaba arkadaşlar yine farklı bir konu ile karşınızdayım.

Uzun zamandır düşündüğüm ama bir türlü yapmaya zaman bulamadığım projemi bugün bitirmiş bulunmaktayım :)
Hepimizin bildiği gibi Dotnet ortamında program geliştirenler programlarını korumak amacı ile Antidump geliştirip programına entegre ederler.
Bizde Antidump kodunun çalıştığı yere geldiğinde durması için çeşitli işlemler yaparak Antidump engelini aşarız.
Böyle oluncada tüm işlemleri tek tek yapmamız gerekmektedir bende böyle sorunları aşmak amacı için ExtremeDumper aracının kodlarını kuracalar iken işime yarayan 2 adet method buldum ve ana programımda kullanım yerlerini değiştirerek daha farklı bir araca dönüştürdüm :D
Ne yaptığıma gelecek olur isem normalde çalışan programı seçerek dump işlemi yapıyorduk artık biz hangi programı seçersek ExtremeDumper içerisinde bulunan dump kodları otomatik olarak hedef programın üzerinde dump edecek hale getirdim diyebilirim :)
Hatta ekstra olarak sık kullanılan bekleme yöntemi ve hangi yöntem ile dump edilebileceğinide eklemiş bulunmaktayım ;)
Peki bu çözümün adına neden Gizli Dumper dediğimide tek satırda açıklar isem tamamen farklı ve sabit olmayan yöntem ile dump işlemi yaptığı ve kullanıcı istediğinde ana pencereyi dahil gizleyebildiği için ;)
Denemelerim sonucunda adının hakkını verdiğini gördüğümü şimdiden belirteyim :)


Unlimited









Programın arayüzü


Alanlara kısaca değineyim
Kod:
dosya => hedef program ister sürükle bırak ister üzerine tıklayarak hedef programı gösterebilirsiniz.
süre => programın çalışıp durdurma süresi gibi düşünebilirsiniz ama buraya öyle bir süre yazmalısınız ki nokta atışı olmalı yoksa antidump çalışıp işinizi bozabilir.
dumper tipi => programı hangi yöntem ile dump etmek istiyorsanız buradan seçebilirsiniz
dump işlemi => eğer sadece size programın kendisi lazım ise ilk seçeneği seçmeniz yeterlidir eğer sonradan dahil edilen dosyalar var ise .dll vb gibi ikinci seçeneği seçebilirsiniz.
özelnitelik => eğer hedef programda bazı başlık kontrolleri yapılıyorsa veya programı görmek istemiyorsanız bu seçeneği seçip programın penceresinin işlem bitinceye kadar gizlemesini sağlayabilirsiniz.

View hidden content is available for registered users!



şifre : revteam.re


kullanılan kodlar :
Kod:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ExtremeDumper.Dumper;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace GizliDumper
{
    public partial class frmDumper : Form
    {

        [Flags]
        public enum ThreadAccess : int
        {
            TERMINATE = (0x0001),
            SUSPEND_RESUME = (0x0002),
            GET_CONTEXT = (0x0008),
            SET_CONTEXT = (0x0010),
            SET_INFORMATION = (0x0020),
            QUERY_INFORMATION = (0x0040),
            SET_THREAD_TOKEN = (0x0080),
            IMPERSONATE = (0x0100),
            DIRECT_IMPERSONATION = (0x0200)
        }
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
        [DllImport("kernel32.dll")]
        static extern uint SuspendThread(IntPtr hThread);
        public frmDumper()

File Dumper

8cn88hm.png
 



Merhaba arkadaşlar yine değişik bir araç konusu ile karşınızdayım :)

Bu aracın hikayesi yaklaşık 5 - 10 sene'ye dayanmakta tabi o zamanl
ar bu kadar tecrübe, bilgi birikimine sahip değildim düşünmüştüm keşke tüm dosyaları dump edebileceğim bir dumper olsaydı diye açıkçası keygen içindeki müziklere vb olan dosyalara erişemediğim için :D
Gün geldi çattı derken bir kaç gün önce duyurduğum autoit a3x dumper aracını yaptıktan sonra az önce bir anda aklıma geldi ve aracı hazırladım.
Bu araçta hedeflediğim şey sizden dosya signature(işaret) bilgisini alıp seçilen programın hafızasında taramak ve aradığınız olabilecek tüm dosyaları kaydetmektir.
Bu sayedede hafızada erişemediğimiz dosyalar kalmayacak sanırım :)
Programın kullanımına gelecek olursak :
1 - hafızadan program seç butonuna basınız ve dosya taraması yapacağınız RAM'de çalışan programın üzerine çift tıklayarak seçiniz.
2 - kayıt edilecek dosya uzantısı alanına bulduğu dosyaların uzantısını yazıyorsunuz mesela .4xm gibi.
3 - çalışan programda aranacak bytelar alanına aradığınız dosya'nın signature(işaret) bilgisini hex olarak ',' ile ayırıp yazıyorsunuz örneğin 0x52,0x49,0x46,0x46 gibi.
4 - Dump Et butonuna basıyorsunuz bulduğu dosyaları kaydedeceği dizini seçmenizi isteyen pencere çıkacaktır seçimi yaptıktan sonra işlem başlayacaktır eğer işlem uzun sürerse veya istediğinizi aldıysanız dump işlemini durdur butonuna basmanız yeterlidir.
Programın arayüzü :


Türkçe:
You must click 'Like' before you can see the hidden data contained here


Kimse belirtmeden ingilizce :
You must click 'Like' before you can see the hidden data contained here


Not:
Programda belirteceğiniz signature(işaret) bilgisine dikkat etmeniz gerekmektedir mutlaka hex olmalı ve , ile ayrılmalıdır aynı zamandada , ile ayırdığınız byteların uzunluğu 2'ye tam bölünmelidir yoksa hata alabilirsiniz.
Dosya signature(işaret) bilgileri için https://www.filesignatures.net/ sitesinden yararlanabilirsiniz ;)
Tüm crack alanındaki arkadaşlarımıza hayırlı olsun (y)


Logic.net

 


Logic.net protector yaptığı önemli kısımlardan ilk olanı string olduğu için string decoder hazırladım ama sabit string çözmesi amaçlı.
Daha sonrada sayısal değerleri karıştıran değerler için ufak bir junk temizleyici yaptım en son olarak <Module> sınıfına konulan basit CRC algoritmasına çıkan method çağırımı temizleyici ile cleaner'ı hazırlamış oldum.
Öncesi:
jr85vr3.png


Sonrası:
escyr4q.png



Arayüz:
1xt502j.png


Kullanımı: "sadece sürükle bırak"

You must click 'Like' before you can see the hidden data contained here


Not:
Çalışmalarıma rağmen bug mevcut ama bu hali iş görmektedir.

Güncelleme 25.03.2022 21:44
Bende yok diye kendim yazmıştım iş görecek kadar meğersem şimdi fark ettim varmış :)



Derli hali:
You must click 'Like' before you can see the hidden data contained here
Deobfuscator: https://s5.dosya.tc/server6/2mvsjt/LogicDeobfuscator.rar.html
Şifre: revteam.re                            
                    

Yano Obfuscator Cleaner

 









Merhaba arkadaşlar duyduğumdan beridir yano obfuscator'ı çok merak ediyordum geçenlerde bakma şansım oldu işi kolaylaştıracak bir cleaner aracı hazırladım ;)

Aracın amacı string çözüp anlamsız if(true) gibi ifadeleri temizleyip de4dot'a fazlası ile yardımcı olmasıdır.

Merak edenler için yano obfuscator : https://yano.informer.com/

Araç ve ders:
You must click 'Like' before you can see the hidden data contained here


Hayırlı olsun (y)


ConfuserEx Entrypoint Fixer







 Merhaba arkadaşlar geçenlerde confuserex ile uğraşırken böyle bir araç lazım olmuştu bende yapayım dedim :)

Aracın yaptığı STAThread attribute kullanan methodu tespit edip entrypoint olarak belirlemesidir aslında bu basit bir işlem ama bazen büyük uygulamalarda entrypoint bulmakta zorlanabiliyoruz.
Classmethod .... vb arama yapmada yada isim uzun olunca dnspy bir hayli kasılıyor hali ile can sıkıcı bir hal alabiliyor.
Fakat bu araç sayesinde uğraşmadan otomatik şekilde entrypoint bulup değiştirme işlemini yapabileceğiz şimdiden herkese hayırlı ve uğurlu olsun (y)