anti-piracy

Just starting out? Need help? Post your questions and find answers here.
User avatar
SPH
Enthusiast
Enthusiast
Posts: 561
Joined: Tue Jan 04, 2011 6:21 pm

anti-piracy

Post by SPH »

Hello,

I would like to talk to you about something that has certainly already been discussed: linking a program to a computer.

I think that, to protect my future PB game, I would link it to the motherboard of the computer that will control the game.

1> do you think that linking it to the motherboard is a good thing (apart from the fact that the player can change hardware)?
2> since it is new to me, I do not know what PB6.12+ offers to link an EXE to a motherboard. Are there any instructions?
3> is this a "hackable" technique?

Thanks for all your expertise on current techniques! :!:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
User avatar
jacdelad
Addict
Addict
Posts: 1991
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: anti-piracy

Post by jacdelad »

I can just speak for myself, but since all anti piracy methods are hackable, I don't think this makes sense for most products. Do think, sorry for asking, your game is worth it to spend time programming anti piracy measures?

On the other hand there are toolkits for that, which are more or less effective.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Joubarbe
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: anti-piracy

Post by Joubarbe »

If you plan to release your game on Steam or Epic, know that they have their own DRM system. You upload the exe, they do their magic, then you download it back and include it in your build. The game can then only be launched if Steam is open, with an account that owns the game.
User avatar
SPH
Enthusiast
Enthusiast
Posts: 561
Joined: Tue Jan 04, 2011 6:21 pm

Re: anti-piracy

Post by SPH »

Joubarbe wrote: Fri Oct 25, 2024 7:59 pm If you plan to release your game on Steam or Epic, know that they have their own DRM system. You upload the exe, they do their magic, then you download it back and include it in your build. The game can then only be launched if Steam is open, with an account that owns the game.
Is it that simple?
In short, you run their EXE and it turns our program into a DRM program that we have to return to Steam?

I am more enlightened, thank you.

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
BarryG
Addict
Addict
Posts: 4120
Joined: Thu Apr 18, 2019 8:17 am

Re: anti-piracy

Post by BarryG »

SPH wrote: Fri Oct 25, 2024 7:42 pmdo you think that linking it to the motherboard is a good thing
Nope. Here's why -> viewtopic.php?p=629226#p629226
miso
Enthusiast
Enthusiast
Posts: 407
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: anti-piracy

Post by miso »

Also, all GOG games comes totally DRM free, and it is still a success.
benubi
Enthusiast
Enthusiast
Posts: 215
Joined: Tue Mar 29, 2005 4:01 pm

Re: anti-piracy

Post by benubi »

I read a blog article and retook the idea in bellow source code, but I can't find a link to the article now.

You can't make it 100% piracy proof, except if you make online verification with "on-the-fly", asymmetric secret keys exchange (public-private-key), repeatedly (every minute or every request) during all the time the software is been used. This then would mean you'd put a lot of effort in (online) authentication so that the secrets can be exchanged and your license be validated, it only shifts the problem to a more remote place from where you can intervene directly as a developer now. (and it may cost bandwidth plus extra costs for the infra structure) There are private companies that propose those services as third party (beside Steam who'd I consider second party).

(removed 80% of the text wall for your comfort)

Anyway here is what I came up with, it allows for a lot of featuritis & over-engineering ;) I also wrote a little "GetMachineID" function for all OS, but I couldn't test it on MacOS. This snippet remains in the drawers, but I may publish it.

Code: Select all

; ==============================================================
; === (c) 2024 by benubi                                     ===
; ==============================================================
;
; Source: MakeCDKey.pb
; Thread: -/-
; Author: benubi 
; Date: Summer 2024
; OS: All
; Description: Generate and/or check for arbitary "Software Keys" with little nested data, using AES encryption
;              UNFINISHED - you can have many options via the flags, I didn't invest too much effort in extra checks like expiration dates & co
;
;
; ============================================================================================================================================================================================================================================================
; ============================================================================================================================================================================================================================================================
; D.O.G. license for MakeCDKey.pb
; Do Only Good with it & be kind to doggo,
; because if you don't he's licensed to bite you.
;
;               ^..^      /
;               /_/\_____/
;                  /\   /\
;                 /  \ /  \
;
; ============================================================================================================================================================================================================================================================
; ============================================================================================================================================================================================================================================================
; Current nested data is:
;
; Structure CDKEYINFO
;   ExpireDate.q       ; optional product expiration or activation date
;   NonceValue.q       ; autokey or serial number of this software key
;   CRC32.l            ; custom CRC32 value. This MUST be zero before SimpleCheckSum() call is made on the data
;   ProductID.u        ; you will have to do with max 64k different products for now ;)
;   ProductFlags.b     ; ExpireDate? DEMO? Professional? Home edition - adapt to your needs
;   ProductMajorVersion.a ; 0-255
;   ProductMinorVersion.a ; 0-255
; EndStructure
;
; Note: If you change/adapt the CDKEYINFO structure you will have to adapt the Make, Check and Extract procedures.
;
; Currently the last character added in the software key tells about an entry in the secret key table,
; so that there are in fact 32 secret entries inside the "secret key table" that may be
; used by the checker procedures for AES encryption. See inside MakeCDKey().
;
; Adapt #MyCDKeySecret in InitCDKey()
; ============================================================================================================================================================================================================================================================
;
; EnableExplicit
;
; #MakeCDKey=0    ; set to 1 if you want to generate CD keys with this compiled executable
; #CheckCDKey=0   ; set to 1 if you want to check & extract CD key info with this compiled executable
;
Procedure.q ReadBits(*Buffer, offset, amount)
  Protected bits_read, *I.BYTE, result.q
  *I = *Buffer + (offset / 8)
  While bits_read < amount
    If *I\b & (1 << (offset & 7))
      result | (1 << bits_read)
    EndIf
    bits_read + 1
    offset + 1
    If offset & 7 = 0
      *I + 1
    EndIf
  Wend
  ProcedureReturn result
EndProcedure
Procedure WriteBits(*Buffer, offset, amount, Bits.q)
  Protected bits_written, *O.BYTE
  Protected bit
  *O = *Buffer + (offset / 8)
  While bits_written < amount
    bit = (Bits >> bits_written) & $1
    If bit
      *O\b = *O\b | (1 << (offset & 7))
    Else
      *O\b = *O\b & ~(1 << (offset & 7))
    EndIf
    bits_written + 1
    offset + 1
    If offset & 7 = 0
      *O + 1
    EndIf
  Wend
  ProcedureReturn bits_written
EndProcedure
;
Structure CDKEYINFO
  ExpireDate.q
  NonceValue.q ; autokey
  CRC32.l
  ProductID.u ;
  ProductFlags.b ; ExpireDate? DEMO? Professional? Home edition
  ProductMajorVersion.a
  ProductMinorVersion.a
EndStructure
;
#CDKEY_CHARS = SizeOf(CDKEYINFO) * 8 / 5 ; 5 = 2^5 aka 32 possible symbols for the software key
;
CompilerIf 1 & $1 = 1 ; LE
  Macro LE_WORD(_W_)
    (_W_)
  EndMacro
  Macro LE_DWORD(_L_)
    (_L_)
  EndMacro
  Macro LE_QWORD(_Q_)
    (_Q_)
  EndMacro
  
CompilerElse
  Macro LE_WORD(_W_)
    ((_W_ & $FF00) >> 8) | ((_W_ & $FF) << 8)
  EndMacro
  Macro LE_DWORD(_L_)
    ((_L_ & $FF000000) >> 24) | ((_L_ & $00FF0000) >> 8) | ((_L_ & $0000FF00) << 8) | ((_L_ & $000000FF) << 24)
  EndMacro
  
  Macro LE_QWORD(_Q_)
    ((_Q_ & $FF000000000000) >> 56) | ((_Q_ & $00FF0000000000) >> 40) | ((_Q_ & $0000FF00000000) >> 24) | ((_Q_ & $000000FF000000) >> 8) | ((_Q_ & $000000FF000000) << 8) | ((_Q_ & $00000000FF0000) << 24) | ((_Q_ & $0000000000FF00) << 40) | ((_Q_ & $000000000000FF) << 56)
  EndMacro
  
CompilerEndIf
;
#CDKEY_MAX_OFFSET = SizeOf(CDKEYINFO) * 8
#CDKEY_VALUES     = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" ; 32 unambiguous symbols (e.g. 1 and 0 ommitted that can be confused with L and O etc.)
;
; You may add/change flags but for now there can only be 8 bits for product flags
#CDKF_Trigger_Expire            = 1   ;
#CDKF_Unlock_software_on_Expire = 2   ; activation date
#CDKF_Lock_On_Expire            = 4   ; expiration date
#CDKF_Free_Major_Upgrades       = 8   ; your app version may be higher than the major version in the nested data
#CDKF_Multi_Users               = 16  ; there can me multiple copies of this key
#CDKF_Beta_Version              = 128 ; this is a beta software version key
;
Procedure.l SimpleCheckSum(*Buff, length) ; Custom CRC32
  Protected q1.l = -721483648 ; IDK if it's good. Change at will
  Protected pos, *B.byte = *Buff
  While pos < length
    q1 * q1
    q1 ! (*B\b * pos)
    pos + 1
  Wend
  ProcedureReturn q1
EndProcedure
;
CompilerIf Not Defined(MakeCDKey, #PB_Constant)
  #MakeCDKey = 1 ; Compile with cd key maker procedure
CompilerEndIf
CompilerIf Not Defined(CheckCDKey, #PB_Constant)
  #CheckCDKey = 1 ; Compile with check & extract procedures
CompilerEndIf
;
DataSection
  key_db_start: 
  ; This will be filled with pseudo-random data or your secret key
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.q 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  ;IncludeBinary "perhaps_my_static_company_logo_is_a_secret_key_table.png"
  key_db_end: ; 
EndDataSection
;
CompilerIf #MakeCDKey
  
; Make
  Procedure$ MakeCDKey(ProductID, ProductFlags, MajorVersion, MinorVersion, NonceValue.q, ExpireDate.q) ; The product ID has to be hard-coded into the SW key checking application, too.
    
    Protected temp.CDKEYINFO
    Protected temp2.CDKEYINFO
    Protected result$
    Protected i
    Protected rNum = NonceValue & 31
    
    Protected Key_Size_Pad = (?key_db_end - ?key_db_start) / 32
    Protected *Key = ?key_db_start + (rNum * Key_Size_Pad)
    Protected *Vec = ?key_db_end - ( (rnum + 1) *Key_Size_Pad)
    
  ; set info values
    temp\ProductID           = LE_WORD(ProductID)
    temp\ProductFlags        = LE_WORD(ProductFlags)
    temp\ProductMajorVersion = MajorVersion
    temp\ProductMinorVersion = MinorVersion
    temp\NonceValue          = LE_DWORD(NonceValue)
    temp\ExpireDate          = LE_QWORD(ExpireDate)
    temp\CRC32               = 0
  ; make checksum
    Protected checksum = SimpleCheckSum(@temp, SizeOf(CDKEYINFO))
    temp\CRC32 = LE_DWORD(checksum)  ;
    
    AESEncoder(@temp, @temp2, SizeOf(CDKEYINFO), *key, 128, *vec)
    
    While i * 5 < #CDKEY_MAX_OFFSET
      result$ + Mid(#CDKEY_VALUES, 1 + ReadBits(@temp2, 5 * i, 5), 1)
      If i % 5 = 4
        result$ + "-"
      EndIf
      i + 1
    Wend
    If Right(result$, 1) = "-"
      result$ = Left(result$, Len(Result$) - 1)
    EndIf
    
    result$ + Mid(#CDKEY_VALUES, 1 + rNum, 1)
  ;result$ = Left(result$, 34)
    ProcedureReturn result$
  EndProcedure
  
CompilerEndIf
;
; check / extract
;
CompilerIf #CheckCDKey
  
  Procedure CheckCDKey(CDKey$, ProductID, CurrentDate.q) ; Product ID is hard-coded into your program
    
    CDKey$ = Trim(CDKey$)
    
    Protected temp.CDKEYINFO
    Protected temp2.CDKEYINFO
    Protected *C.character = @CDKey$
    Protected offset = 0
    Protected t.q
    Protected result
    Protected rNum = FindString(#CDKEY_VALUES, Right(CDKey$, 1)) - 1
    
    Protected Key_Size_Pad = (?key_db_end - ?key_db_start) / 32
    Protected *Key = ?key_db_start + (rNum * Key_Size_Pad)
    Protected *Vec = ?key_db_end - ( (rnum + 1) *Key_Size_Pad)
    
    If rnum = -1
      ProcedureReturn 0
    EndIf
    
    While *C\c And offset < #CDKEY_MAX_OFFSET
      t = FindString(#CDKEY_VALUES, Chr(*C\c))
      If t
        WriteBits(@temp, offset, 5, t - 1)
        offset + 5
      EndIf
      *C + SizeOf(Character)
    Wend
    
    AESDecoder(@temp, @temp2, SizeOf(CDKEYINFO), *Key, 128, *Vec)
    
    Protected checksum = (temp2\CRC32)
    checksum    = LE_DWORD(checksum)
    temp2\CRC32 = 0
    
    
    If SimpleCheckSum(@temp2, SizeOf(CDKEYINFO)) = checksum
      result | 1
   ; Debug "checksum ok"
      If LE_WORD(temp2\ProductID) = LE_WORD(ProductID)
        result | 2
      ;Debug "product id ok"
      EndIf
      If temp2\ExpireDate <= 0 Or temp2\ExpireDate > CurrentDate
     ; Debug "expire date ok"
        result | 4
      EndIf
    EndIf
    
    
    
    ProcedureReturn result ; 31 = all checks succeeded ??
  EndProcedure
  
  Procedure ExtractCDKeyInfo(CDKey$, *Info.CDKEYINFO) ; returns non-zero if the extracted data is valid
    CDKey$ = Trim(CDKey$)
    Protected temp.CDKEYINFO
    Protected temp2.CDKEYINFO
    Protected *C.character = @CDKey$
    Protected offset = 0
    Protected t.q
    Protected result
    Protected rNum = FindString(#CDKEY_VALUES, Right(CDKey$, 1)) - 1
    
    Protected Key_Size_Pad = (?key_db_end - ?key_db_start) / 32
    Protected *Key = ?key_db_start + (rNum * Key_Size_Pad)
    Protected *Vec = ?key_db_end - ( (rnum + 1) *Key_Size_Pad)
    
    If rnum = -1
      ProcedureReturn 0
    EndIf
    
    While *C\c And offset < #CDKEY_MAX_OFFSET
      t = FindString(#CDKEY_VALUES, Chr(*C\c))
      If t
        WriteBits(@temp, offset, 5, t - 1)
        offset + 5
      EndIf
      *C + SizeOf(Character)
    Wend
    
    
    AESDecoder(@temp, @temp2, SizeOf(CDKEYINFO), *Key, 128, *Vec)
    
    Protected checksum = (temp2\CRC32)
    checksum    = LE_DWORD(checksum)
    temp2\CRC32 = 0
    
    
    If SimpleCheckSum(@temp2, SizeOf(CDKEYINFO)) = checksum
      result | 1
      
      If *Info
        *Info\ProductID           = LE_DWORD( temp2\ProductID )
        *Info\ProductFlags        = LE_WORD(temp2\ProductFlags)
        *Info\ProductMajorVersion = temp2\ProductMajorVersion
        *Info\ProductMinorVersion = temp2\ProductMinorVersion
        *Info\NonceValue          = LE_QWORD(temp2\NonceValue)
        
        *Info\ExpireDate = LE_QWORD(temp2\ExpireDate)
        *Info\CRC32      = checksum
      EndIf
    EndIf
    
    ProcedureReturn result ; 31 = all checks succeeded
    
  EndProcedure
  
CompilerEndIf
;
Procedure InitCDKey() ; This procedure has to be present in key maker and checker. Adapt random values.
  UseMD5Fingerprint()
  Define oldrandom = Random($7FFFFFFF)
  #MyCDKeySecret   = 20050329 ; the date I joined the english speaking forum, of course ;o)
  RandomSeed(#MyCDKeySecret)
  RandomData(?key_db_Start, ?key_db_end - ?key_db_start)
  RandomSeed(oldrandom)
EndProcedure

; ----------------- DEMO --- MAKE & CHECK CD KEYS ------------------------
CompilerIf #PB_Compiler_IsMainFile
  ;
  DisableExplicit
  ;
  InitCDKey()
  ;
  remember$ = ""
  ;
  For i = 10001 To 10100 ; serial numbers / auto key
    key$ = MakeCDKey(1001, 23, 2, 0, i, -1) ; 
    Debug LSet(Str(i) + ".", 5) + " " + key$ + ": " + StringField("BAD|OK", 1 + (1*Bool(CheckCDKey(key$, 1001, -1))), "|")
    
    If Random(10) > 9
      remember$ = key$
    EndIf
  Next
  ;
  Debug "secret AES key length (table):"
  Debug ?key_db_end - ?key_db_start
  ;
  result$ = MakeCDKey(1001, 23, 2, 0, 10000, -1)
  ;
  Debug "CD-Code length (without dash): " + Len(RemoveString(Result$, "-"))
  Debug "CD Key info structure size (guessed): " + StrD( - 1 + Len(RemoveString(Result$, "-")) * 5 / 8, 2)
  Debug "CD Key info structure size: " + SizeOf(CDKEYINFO)
  Debug "CDKEY : " + result$
  Debug "Check CD Key: " + Str(CheckCDKey(result$, 1001, 0))
  ;
  Define myinfo.CDKEYINFO
  ;
  Debug "Remembered key: " + remember$
  ;
  If ExtractCDKeyInfo(remember$ + remember$, @myinfo)
    Debug "Product ID:    " + myinfo\ProductID
    Debug "Product flags:  " + myinfo\ProductFlags
    Debug "Major version:  " + myinfo\ProductMajorVersion
    Debug "Minor version:  " + myinfo\ProductMinorVersion
    Debug "Nonce value:    " + myinfo\NonceValue
    Debug "Expir. date:    " + myinfo\ExpireDate
    Debug "checksum:       " + myinfo\CRC32
  Else
    Debug "ExtractCDKey failed"
  EndIf
  ;
CompilerEndIf
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: anti-piracy

Post by Thorium »

benubi wrote: Mon Oct 28, 2024 3:48 pm Anyway here is what I came up with, it allows for a lot of featuritis & over-engineering ;) I also wrote a little "GetMachineID" function for all OS, but I couldn't test it on MacOS. This snippet remains in the drawers, but I may publish it.
The problem with it is that is is really easy to crack. Takes a couple of minutes to patch the .exe to take any key.
It's a lot of effort to implement it and inconvenience for the costumer. Not worth it in my opinion.
User avatar
SPH
Enthusiast
Enthusiast
Posts: 561
Joined: Tue Jan 04, 2011 6:21 pm

Re: anti-piracy

Post by SPH »

Have you ever heard that a steam game was pirated?
Me, no. And that's ultimately why I'm going to choose steam. Plus, I wouldn't have to do all the work of unique serials for each player...

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
User avatar
jacdelad
Addict
Addict
Posts: 1991
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: anti-piracy

Post by jacdelad »

SPH wrote: Wed Nov 06, 2024 4:00 pm Have you ever heard that a steam game was pirated?
Me, no. And that's ultimately why I'm going to choose steam. Plus, I wouldn't have to do all the work of unique serials for each player...
Yes, effectively all of them. There's a lot of sites where you can them in bundles of hundreds. There's also tools which automatically remove the Steam protection, so you can spread the games you paid for everywhere. And there's people who exactly do this.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: anti-piracy

Post by Quin »

Like I always say, nothing is unbreakable. You just have to make it not worth your attacker's time. :wink:
miso
Enthusiast
Enthusiast
Posts: 407
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: anti-piracy

Post by miso »

Looks like it has become more or less an offtopic, rather than coding questions. Still, I would like to share my observation.
(And it is subjective, personal opinion.)

As a developer, all of us wants to be rewarded for their hard work, so it's not the devils work to think about some defense.
In the past, companies used all kinds of DRM for that reason, but later on they stepped trough a line. Some of you might remember how treacherous and malicious Starforce III was.

Nowadays (as a best protection) they requires online present. Part of the software is not local, but remote. It's safe, but a burden for the user.
(some of my friends work in the video industry, using adobe premier and a couple of related product) There were a lot of swearing with new upgrades
that broke already working old functions, and they could not roll back to an older version. Also, this kind of protection generates a lot of hate, that redirect the related industry to find replacement solutions. And they sometimes do.

Crackers are a strange subculture. They do not profit at all in their work, they are only up for the thrill of the challange.
New release? My team will crack it first, and show all the other teams, that we are the best. Hold my beer.
I belive most of them has a good job somewhere, and it is just their hobby.

Pirates? Either don't have money, or they not sure if your product is something they want. They might try it and delete it. Some of them will find it good, and make a purchase that would not happen otherwise. Either way, I find impossible to completely evade piracy. I try to look at it as free marketing.

When Good Old Games started, it said, all their product will be DRM free. You are not allowed to share the product to anyone, but all annoying defense is removed. It is kept through all these years, still, their sales are not bad at all.
For me, it is proved, I don't need any DRM in my products.

Also, if you are targeting companies with your product, they won't use unlicensed softwares anyway.
plouf
Enthusiast
Enthusiast
Posts: 281
Joined: Fri Apr 25, 2003 6:35 pm
Location: Athens,Greece

Re: anti-piracy

Post by plouf »

SPH wrote: Fri Oct 25, 2024 7:42 pm

I think that, to protect my future PB game, I would link it to the motherboard of the computer that will control the game.
a pb user has created something like you are searching for -> https://www.pahlabs.com/product/productpbxlicense/
maybe its helpfull to you to reduce development time !?
Christos
Rinzwind
Enthusiast
Enthusiast
Posts: 679
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: anti-piracy

Post by Rinzwind »

Btw Steam doesn't magically protect your exe. There are many games, even of bigger publishers, which remain working after getting a refund.
Post Reply