Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C, PHP, VB6: Suojausvinkki

Sivun loppuun

jtha [05.02.2011 12:28:23]

#

Noniin, minulla on VB6-sovellus(piirustusohjelma), jota käytän suoraan usb-tikulta Windows pohjaisissa koneissa.

(Halusin aikoinaan sovelluksesta sellaisen, että se ei tarvitse erillistä asennusta vaan toimi itsenäisesti yhtenä .exe failina. Tämä mahdollista asiakkaan koneen käytön tarvittaessa. Ei ocx dll eikä mitään erikoista koodissa, vain ihan perusobjekteja, ei myöskään tietokantaa vaan failien käyttöä randomina.)

Ohjelma toimii ja olen tehnyt sillä sähkösuunnittelua koneisiin jo jonkin aikaa. Muutamalla asiakkaalla ja kolleegalla on ollut kiinnosstusta ohjelmasta, joten olen ajatellut kehittää siihen "käyttöoikeus"-ominaisuutta. Voisin sitten antaa/myydä käyttöoikeutta vaikka vuodeksi kerrallaan tms.??

Kehittelin kokeeksi systeemin, jossa käyttäjä antaa ohjelmalle kaksi tekstiriviä: "Käyttöaika & Nimi & Osoite & MuutYhteystiedot ..." sekä koodi "siansaksaaaaaaaa..." ja näiden tekstien pitää tietyllä algoritmillä pitää kutinsa keskenään. Tähän käytin n. 1MB kokoista siansksataulukkoa josta eka teksti hakee toisen tekstin kirjaimet.

Asiakkaan tiedot(teksti 1.) näkyyvät kaikissa tulostuksissa, joten tämä mahdollisesti ehkäisee luvatonta käyttöä - vai ehkäiseekö?

No, itsestänikin tämä vaikuttaa vähintäänkin ontuvalta ja koen osaamiseni tässä epävarmaksi (ja oletettavasti joku ammattilainen osaa murtaa tämän systeemin muutamassa sekunnissa)

Onko teillä suositusta miten lähtisin asiaa kehittämään? Onko mielestänne ylipäätään mahdollista suojata USB-tikulta suoritettavaa täysin itsenäistä ohjelmaa?

Grez [05.02.2011 12:38:32]

#

Mitään ohjelmaa, jota suoritetaan käyttäjän koneella, ei ole mahdollista suojata niin, että sitä ei voisi murtaa.

Itse käyttäisin asymmetristä salausta. Eli tekisin niin, että laittaisin lisenssitiedot selväkielisinä ja sitten omalla salaisella avaimellani allekirjoittaisin sen. Ohjelman mukana tulisi julkinen avain, jolla sitten allekirjoitus varmennettaisiin.

Tämänkin toki pystyy kiertämään muokkaamalla ohjelmaa. Mutta avaingeneraattoria ei pysty tekemään, joten muokkailu täytyy tehdä uudestaan jokaiselle uudelle versiolle.

jtha [05.02.2011 22:16:59]

#

Onkos tietoa voiko USB-muisteja yksilöidä, joten ohjelmaa olisi mahdollista käyttää vain tietyltä tikulta? Ohjelman levitys tapahtuisi siis tikun avulla.

(Yritin etsiä jotakin MAC-osoitteen tapaista yksilöivää tietoa ja joitakin arvoja löytyykin ominaisuus ikkunan kautta, mutta en tiedä mitä ne itseasiassa ovat.)

-tossu- [05.02.2011 23:26:25]

#

jtha kirjoitti:

Onkos tietoa voiko USB-muisteja yksilöidä, joten ohjelmaa olisi mahdollista käyttää vain tietyltä tikulta? Ohjelman levitys tapahtuisi siis tikun avulla.

Googlella löytyi ohjelma nimeltään AntiDuplicate, joka väittää osaavansa yksilöidä ohjelman tiettyyn USB-muistiin. Ohjeman sivuilla ei kylläkään sanota, millä tavoin se tarkistaa muistitikun alkuperäisyyden, mutta vastaavanlaisen virityksen saanee itsekin tehtyä.

jtha [06.02.2011 00:47:42]

#

Kiitos -tossu-! Ehdottomasti pitää tutkia tuo mahdollisuus.

groovyb [07.02.2011 13:19:29]

#

itse tein yhteen sovellutukseen salauksen rijndaelilla, ja valmiita avainpareja parituhatta.

kun asiakas asensi sovellutuksen, ohjelmaan syötettiin avainparin asiakaspuolen koodi.

Tämän jälkeen softa otti yhteyden palvelimelle ja varmensi avaimen parin (ja poisti käyttölistalta).

Jos verkkoyhteyttä ei ollut, asiakas soitti firmaan ja pyysi salauksen avainparin (softa arpoi randomilla yhden avainparin listalta).

tämän jälkeen kyseinen pari poistettiin lisenssilistalta.

Lebe80 [07.02.2011 15:38:22]

#

Me taas tehtiin jokunen vuosi sitten eräänlainen "suojaus" "multimediarompulle", jonka tarkoitus oli estää kyseisen yritysten myyjiä käyttämästä vanhentunutta versiota rompusta myyntitöissä.

Ajatus olikin kiva aluksi, kunnes huomasimme jok'ikinen vuosi olevamme päivittämässä romppua pahimman joulukiireen alla.

Grez [07.02.2011 15:54:57]

#

No olisiko ekalla kerralla kannattanut vaihtaa vanhenemispäivä vaikka heinäkuulle?

Sinänsä Leben tapauksessa ei tarvitse kovin monimutkaista "suojausta", kun voidaan olettaa että sitä ei lähde kukaan hakkeroimaan.

Tuosta groovyb:n viestistä tuli minulle enemmän kysymyksiä kuin vastauksia. Oliko siis koko systeemi kryptattuna ja se purettiin muistiin? Jos kerran ekan käyttökerran jälkeen avaimen toinen puolikas poistettiin käyttölistalta, niin oliko se sitten kertakäyttöinen sovellus. Vai menikö se niin, että ekan tarkistuksen yhteydessä avaimen toinen puolikas tallennettiin jemmaan käyttäjän koneelle vai peräti koko softa salaus purettuna?

neau33 [07.02.2011 17:25:56]

#

Moi jtha!

tässä pikku esimerkki USB-tikun tsekkaamiseen...

Private Declare Function GetDriveType Lib "kernel32" _
Alias "GetDriveTypeA" (ByVal nDrive As String) As Long

Private Sub Form_Load()

   Dim root As String
   root = Left(App.Path, 3)

   Dim msg As String

   If GetDriveType(root) <> 2 Then
      msg = "EI KÄYTTÖOIKEUTTA!" 'Esim.
   End If

   Dim driveletter As String
   driveletter = UCase(Left(root, 1))

   Select Case driveletter
      Case "A", "B"
      msg = "EI KÄYTTÖOIKEUTTA!"
   End Select

   Dim fullpath As String
   fullpath = root & "mydrive.dat"

   If Dir(fullpath) <> "" Then
      Kill fullpath
   End If

   Shell "cmd /C dir root >" & fullpath, vbHide

JumpBack:
   On Error Resume Next
   flen& = FileLen(fullpath)
   If Err <> 0 Then
      Err.Clear
      On Error GoTo 0
      GoTo JumpBack
   End If

   Do While FileLen(fullpath) = 0
   DoEvents: Loop

   Dim rootdata As String
   Open fullpath For Input As #1
   rootdata = Input$(LOF(1), 1)
   Close #1

   Shell "cmd /C del " & fullpath, vbHide

                      'Huom! ko. tikun serial
   If InStr(rootdata, "3B67-0B4F") = 0 Then
      msg = "EI KÄYTTÖOIKEUTTA!"
   End If

   If msg <> "" Then
      Dim msgresult As Long
      msg = msg & vbCrLf & _
      "Tahdotko siirtyä ohjelman toimittajan Internet sivustolle?"
      msgresult = MsgBox(msg, vbYesNo, Me.Caption)
      If msgresult = 6 Then
        Shell "explorer http://www.sivusto.com", vbNormalFocus
      End If
      End
   End If

   '...

End Sub

Ton käyttöoikeus-jutskan vois järjestää vaikkapa niin, että virittelis jokun ilmasen tahi huokean web-hotellin servulle PHP/MySql viritelmän jonne lähettelis WinInet API:n avulla sivun headereihin ao. tikun seriaalin ja responsena tulis sit tieto siitä onko lisenssi voimassa vaiko eikö...
täältä löytyy sample, jonka avulla tutustua WinInet API'n saloihin jos ei ole ennestään tuttua.

groovyb [07.02.2011 17:44:14]

#

Grez,ohjelman järjestelmätiedot oli kryptattu, ja kryptaus purettiin aina käynnistyksen yhteydessä. Jos ohjelma asennettiin uudelleen,piti myös avaimet uusia. Listalta poisto sen takia ettei verkkovarmenteessa voinut käyttää samaa avainta kahdesti.

jtha [07.02.2011 19:57:59]

#

Minä tein tämän seuraavasti(toistaiseksi):
Etsin netistä vb6-koodin, jolla saadaan listattua usb-muistit, jotka ovat koneessa kiinni. Samalla saan muisteista luettua mm. valmistajan nimen ja muistin sarjanumeron. Muodostin tikun tiedoista ja lisenssinhaltijasta ym. tiedoista merkkijonon, jolle hain vastineen "siansakasaa" tietyllä algoritmilla. Nyt tallennan sovelluksen ja lisenssi ja siansksat ko. tikulle. Sovellus puolestaan lukee nämä tiedot faileista sekä usb-tikun sarjanumeron yms. ja hakee samalla algoritmillä "siansksa"-koodin, jonka on oltava sama kuin faileihin on upotettu. Nyt tämä softa siis toimii vain ja ainoastaan tällä yhdellä usb-tikulla. Brutaalia ehkä, mutta tuntuu toimivan.

Algoritmi, joka muodostaa siansaksan on mielestäni aika hankalasti arvattavissa, mutta olisi tietysti kiva testauttaa jollakin hakkerilla :-)

Grez [07.02.2011 20:43:51]

#

jtha kirjoitti:

Algoritmi, joka muodostaa siansaksan on mielestäni aika hankalasti arvattavissa, mutta olisi tietysti kiva testauttaa jollakin hakkerilla :-)

Murtuu 15 minuutissa. Mutta tuskin sillä on merkitystä koska ei varmaan ohjelman kohderyhmää kiinnosta alkaa hakkeroimaan. Tai jos joku niin tekee niin tuskin kovin moni.

Lebe80 [07.02.2011 20:54:09]

#

neau33:n vinkkiin muuttaisin (todennäköisesti vitseiksi tarkoitetut) "fak juut" oikeasti joksikin vähääkään kuvaavimmiksi.

Muutenkin mm. Ohjelmointiputkan foorumilla näkee keskusteluissa paljon "virheilmoituksia", joista monet ovat oppineet käyttämään niitä väärin. Olen jokusen kerran myös eksynyt ihan vanhentuneesta linkistä sivulle, jossa minua tervehditään lämpimästi "Hacking attempt" -tervehdyksellä.

Eli jottei koskaan enää ikinä vahingossakaan mikään ohjelma ilmoittaisi noin vulgaaristi mistään, niin olisi hyvä, että kokemattomille koodareille annettaisiin vinkkejä, joissa ei heti haistatettaisi värkkejä ja haukuttaisi hakkereiksi, koske monille vinkit opettavat oikeasti koodaamaan virheilmoituksiin noita termejä.

Muutenkin omalla alalla olen saanut lukea paljon juttuja, joissa kolmen aikaan yöllä väliaikaisiksi tarkoitetut "vitsit" ovatkin jääneet kummittelemaan ihan asiakkaan versioihin.

Toteuttaisin Grezin neuvoa, ja en viitsisi nähdä vaivaa kovinkaan monimutkaisen suojauksen tekemiseen, vaan tyytyisin siihen, ettei softaa esim. vahingossa pääsisi levittämään eteenpäin.

jtha [07.02.2011 21:07:29]

#

Hyviä mielipiteitä.

Kuitenkin, jos joku viitsii vaikka murtaa tuon, niin ilmoittakaa kauanko meni, tarjoan kaljan vaikka sen peliprojektin julkistamistilaisuudessa.

(http://www.jth-automaatio.fi/ohj_putka_jtha.zip)

Grez [07.02.2011 21:17:41]

#

Mitä tarkoitat murtamisella? Eikös tuo ole jo itsessään työkalu mikä tekee sen mitä voisin kuvitella murtamistyökalun tehtävän olevan.

jtha [07.02.2011 21:29:48]

#

Meinaan että ilman tuota pitäisi saada aikaiseksi selväkielisestä tekstistä sama koodi. Jos onnistuu helposti saamaan vastaavan koodin omin avuin niin sen voi liittää tiedostoihin keksittyjen käyttöoikeuksien kanssa ja alkuperäisen käyttöoikeuden voi helposti kiertää... äh, olenkohan suistumassa ojasta allikkoon tämän kanssa...

Grez [07.02.2011 22:01:47]

#

Täytyy sanoa että ei ole tullut harrastettua hakkerointia, mutta tiedän suurinpiirtein mitä tapoja kiertää kuvaamasi tyylisiä suojauksia on olemassa.

Ehkä nopein tapa on etsiä koodista kohta joka antaa esimerkiksi virheilmoituksen väärästä lisenssistä ja kelata siitä taaksepäin että missä se tarkistettiin ja sitten vaikka muuttaa koodia siten että tarkistuksen tulos on aina positiivinen.

Jos tarvitsee vaan yksi avain saada, niin voisi debuggerissa ajaa ohjelmaa ja kun ohjelma on laskenut oikean avaimen, jota alkaa vertaamaan käyttäjän syöttämään, niin kopioi sen lasketun oikean avaimen talteen.

Jos haluaa tehdä ihan koodigeneraattorin (mitä siis hait tässä), niin sen tekeminen on tietty hieman työläämpää kuin edellä mainitut suojauksen ohittamiset. Yksi tapa on tuktia mitä ohjelma tekee. Voisin sen tässä tehdä jos olisi ylimääräistä aikaa. (Tästä hassu offtopicci lopussa) Ja sitten kirjoittaa koodin joka tekee saman asian. Tai vielä yksinkertaisemmin, kopioi sen koodin laskevan koodinpätkän ohjelmasta ja upottaa sen omaan avaingeneraattoriin lähes sellaisenaan.

Offtopiccia:
Pitäis varmaan joskus leikkiä enemmän X86 assemblerin kanssa. Tullut puuhailtua lähinnä 68k prossujen kanssa aikanaan ja sitten mikrokontrollereilla.

Miksiköhän toi VB6 kääntäjä tekee tällaista. Siis selvästikin kutsumista varten lataillaan muuttujista arvoja, mutta jos ne kerran pusketaan pinoon lataamisen jälkeen, niin miksi jokainen vedetään eri rekisterin kautta?

Ja miksi tossa ei ole push aina heti lea:n jälkeen vaan se ennakoi yhden lea:n

Jos arvailla pitäisi niin liittyy jotenkin koodin optimointiin.

loc_00402081: lea edx, var_74
loc_00402084: lea eax, var_A4
loc_0040208A: push edx
loc_0040208B: lea ecx, var_84
loc_00402091: push eax
loc_00402092: push ecx
loc_00402093: mov var_9C, 00401920h ; "\el_m_draw_varmuuskoodit.rnd"
loc_0040209D: mov var_A4, 00000008h
loc_004020A7: call [00401080h]

jtha [08.02.2011 00:04:21]

#

Hei, Grez.

Tuo esittämäsi koodinpätkä on VB6:ssa seuraava:
("TunnisteKoodi" unohtui siihen kun kopsasin sen piirustusohjelmasta)
Selventäneekö tämä tuon konekielisen?(assembler?)-koodin rakennetta..

Private Sub Command1_Click()

  Dim Koodi As String

  n = FreeFile
  Open CurDir & "\el_m_draw_varmuuskoodit.rnd" For Random As n Len = 1
    pit = LOF(n)
    OtaKoodiTaulukosta n, pit, TunnisteKoodi & Text1.Text, Koodi
  Close n
  Text2.Text = Koodi

End Sub

Näyttää tosiaan siltä, että koodin tekevän algoritmin voi kopsata .exe failista kun homman osaa. Tämä kaikki selventää ajatuksiani, kiitoksia.

Grez [08.02.2011 00:17:24]

#

lainaus:

Selventäneekö tämä tuon konekielisen?(assembler?)-koodin rakennetta..

Ei siinä sinänsä mitään epäselvää ollut. En vaan ole itse hirveän harjaantunut x86-koodin lukija niin koko ohjelman toiminnan selvittämiseen mennisi minulta aika paljon aikaa.

Tuo kyseinen laittamani pätkä vastaa suunnilleen osaa:
& "\el_m_draw_varmuuskoodit.rnd"

Curdir oli aikaisemmin koodissa ja open on myöhemmin. Sinänsähän yhdestä VB6 -koodirivistä tulee helposti 20-50 riviä assemblyä, joten ei tuollaisen koodin toiminnan selvittäminen tietenkään hirveän nopeaa ole, varsinkaan jos ei ole harjaantunut assemblyn lukija. Itse piti ihan aluksi tarkistaa mitä tarkoittaa lea :D

Mutta tosiaan ohjelmien murtamiseen harjaantunut hakkeri murtaa tuollaisen suojauksen nopeasti. Kuten ihan alussa sanoin, niin mitään käyttäjän tietokoneella ajettavaa koodia ei ole mahdollista suojata niin, että sitä ei voisi murtaa. Tietenkin työmäärän kasvaessa hyöty pienenee. Ja kannattaa muistaa myös että ohjelmien luvaton käyttö on laitonta, joten asialliset firmat ei sitä tee vaikka ei mitään suojausta olisikaan. Tietty jos pääasiallinen asiakaskunta on pienet pajat ja ohjelman hinta on hirmuinen, niin suojaus voi olla tärkeää.

neau33 [08.02.2011 07:28:15]

#

Heippa taas!

tässä vielä hieman aiheesta...

'Form1
(lisää vb-koodi ohjelmaasi, käännä ja tallenna .exe tikulle)
Private Declare Function GetDriveType Lib "kernel32" _
Alias "GetDriveTypeA" (ByVal nDrive As String) As Long

Dim xhttp As MyHttpClass

Private Sub Form_Load()

   TsekkaaOikeudet

   '...

End Sub

Private Sub TsekkaaOikeudet()

   If Not Internet.Connected Then
     MsgBox "Ei Internet-yhteyttä!"
     End
   End If

   Dim root As String
   root = Left(App.Path, 3)

   Dim msg As String

   If GetDriveType(root) <> 2 Then
     msg = Space(30) & "EI KÄYTTÖOIKEUTTA!" 'Esim.
   End If

   Dim driveletter As String
   driveletter = UCase(Left(root, 1))

   Select Case driveletter
     Case "A", "B"
       msg = Space(30) & "EI KÄYTTÖOIKEUTTA!"
     Case Else
   End Select

   Dim fullpath As String
   fullpath = root & "mydrive.dat"

   If Dir(fullpath) <> "" Then
     Kill fullpath
   End If

   Shell "cmd /C dir root >" & fullpath, vbHide

JumpBack:
   On Error Resume Next
   flen& = FileLen(fullpath)
   If Err <> 0 Then
     Err.Clear
     On Error GoTo 0
     GoTo JumpBack
   End If

   Do While FileLen(fullpath) = 0
   DoEvents: Loop

   Dim rootdata As String
   Open fullpath For Input As #1

   Do While Not LOF(1)

     Input #1, rootdata

     If InStr(rootdata, "Aseman sarjanumero on") > 0 Then
        rootdata = Trim(Replace(rootdata, _
        "Aseman sarjanumero on", ""))
        Exit Do
     End If

   Loop

   Close #1

   Shell "cmd /C del " & fullpath, vbHide

   Set xhttp = New MyHttpClass

   If xhttp.OpenHTTP("localhost") Then
    Dim response As String
    response = xhttp.SendRequest( _
    "/ohjelmisto/tsekkaa.php?lisenssi=" & rootdata, "POST")

    If Trim(response) = "nolicense" Then
      msg = Space(30) & "EI KÄYTTÖOIKEUTTA!"
    ElseIf Trim(response) = "expired" Then
      msg = Space(25) & "KÄYTTÖOIKEUS PÄÄTTYNYT!"
    ElseIf InStr(response, "daysleft") > 0 Then
      Dim daysleft As String
      daysleft = Trim(Replace(response, "daysleft", ""))
      MsgBox "KÄYTTÖOIKEUS VANHENEE " & daysleft & " PÄIVÄN KULUTTUA!"
    End If

   End If

   Set xhttp = Nothing

   If msg <> "" Then
     Dim msgresult As Long
     msg = msg & vbCrLf & vbCrLf & _
     "Tahdotko siirtyä ohjelman toimittajan Internet sivustolle?"
     msgresult = MsgBox(msg, vbYesNo, Me.Caption)
     If msgresult = 6 Then
       Shell "explorer http://www.palvelimesi.com/sivustosi", vbNormalFocus
     End If
     End
   End If

End Sub
'Module1
Private Declare Function InternetGetConnectedState Lib _
"wininet.dll" (ByRef lpSFlags As Long, _
ByVal dwReserved As Long) As Long

Public Type InternetConnection
   Connected As Boolean
End Type

Public Function Internet() As InternetConnection
   Dim cType As Long
   Internet.Connected = InternetGetConnectedState(cType, 0&)
End Function
'MyHttpClass (Class Module)
Option Explicit

Public Enum ePort
   INTERNET_DEFAULT_HTTP_PORT = 80
   INTERNET_DEFAULT_HTTPS_PORT = 443
End Enum

Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_SERVICE_HTTP = 3

Private Const INTERNET_FLAG_PRAGMA_NOCACHE = &H100
Private Const INTERNET_FLAG_KEEP_CONNECTION = &H400000
Private Const INTERNET_FLAG_SECURE = &H800000
Private Const INTERNET_FLAG_FROM_CACHE = &H1000000
Private Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000
Private Const INTERNET_FLAG_RELOAD = &H80000000

Private Const BUFFER_LENGTH As Long = 1024

Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
(ByVal Agent As String, ByVal AccessType As Long, ByVal ProxyName As String, _
ByVal ProxyBypass As String, ByVal Flags As Long) As Long
Private Declare Function InternetConnect Lib "wininet.dll" Alias _
"InternetConnectA" (ByVal hInternetSession As Long, ByVal ServerName As String, _
ByVal ServerPort As Integer, ByVal UserName As String, ByVal Password As _
String, ByVal Service As Long, ByVal Flags As Long, ByVal Context As Long) As _
Long
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As _
Long) As Boolean

Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hConnect As _
Long, ByVal Buffer As String, ByVal NumberOfBytesToRead As Long, _
NumberOfBytesRead As Long) As Boolean

Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias _
"HttpOpenRequestA" (ByVal hHttpSession As Long, ByVal Verb As String, ByVal _
ObjectName As String, ByVal Version As String, ByVal Referer As String, ByVal _
AcceptTypes As Long, ByVal Flags As Long, Context As Long) As Long
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias _
"HttpSendRequestA" (ByVal hHttpRequest As Long, ByVal Headers As String, ByVal _
HeadersLength As Long, ByVal sOptional As String, ByVal OptionalLength As Long) _
As Boolean

Private hHTTP As Long
Private hConnection As Long

Private Const FIELDS_BUFFER_LENGTH As Long = 10
Private Const FIELDS_NAME_INDEX As Long = 0
Private Const FIELDS_VALUE_INDEX As Long = 1

Private DontEncode(255) As Boolean

Private FieldCount As Long
Private mFields() As String

Public Property Let Fields(Name As String, Value As String)

   mFields(FIELDS_VALUE_INDEX, GetFieldIndex(Name, True)) = Value

End Property

Public Property Get Fields(Name As String) As String

   Dim l As Long

   l = GetFieldIndex(Name, False)
   If l > -1 Then
     Fields = mFields(FIELDS_VALUE_INDEX, l)
   End If

End Property

Public Function OpenHTTP(Server As String, Optional Port As ePort = _
INTERNET_DEFAULT_HTTP_PORT, Optional UserName As String, Optional Password As _
String) As Boolean

   CloseHTTP

   hHTTP = InternetOpen("HTTP Client", INTERNET_OPEN_TYPE_DIRECT, UserName, _
   Password, 0)
   If hHTTP <> 0 Then
     hConnection = InternetConnect(hHTTP, Server, INTERNET_DEFAULT_HTTP_PORT, _
     UserName, Password, INTERNET_SERVICE_HTTP, 0, 0)
     If hConnection <> 0 Then
       OpenHTTP = True
     Else
       InternetCloseHandle hHTTP
       hHTTP = 0
     End If
   End If

End Function

Public Sub CloseHTTP()

   If hConnection <> 0 Then
     InternetCloseHandle hConnection
   End If

   hConnection = 0

   If hHTTP Then
     InternetCloseHandle hHTTP
   End If

   hHTTP = 0

End Sub

Public Function SendRequest(ByVal File As String, Optional Method As String = _
"GET", Optional Referer As String, Optional Reload As Boolean = True) As String

   Dim hRequest As Long
   Dim r As Boolean
   Dim Buffer As String
   Dim Header As String
   Dim Request As String
   Dim POSTData As String
   Dim response As String
   Dim Read As Long
   Dim Flags As Long

   Method = UCase$(Method)
   Request = BuildRequest
   Buffer = Space$(BUFFER_LENGTH)

   If Len(Request) > 0 Then
     If Method = "POST" Then
       Header = "Content-Type: application/x-www-form-urlencoded"
       POSTData = Request
     Else
       File = File & "?" & Request
     End If
   End If

   If Reload Then
     Flags = Flags Or INTERNET_FLAG_PRAGMA_NOCACHE Or INTERNET_FLAG_RELOAD
   End If

   hRequest = HttpOpenRequest(hConnection, Method, File, "HTTP/1.1", "", 0, _
   Flags, 0)
   If hRequest <> 0 Then
     If HttpSendRequest(hRequest, Header, Len(Header), POSTData, _
     Len(POSTData)) Then
       r = InternetReadFile(hRequest, Buffer, BUFFER_LENGTH, Read)
       While r And (Read <> 0)
         response = response & Left$(Buffer, Read)
         r = InternetReadFile(hRequest, Buffer, BUFFER_LENGTH, Read)
       Wend
     End If
     InternetCloseHandle hRequest
   End If

   SendRequest = response

End Function

Private Function GetFieldIndex(Name As String, Optional Add As Boolean) As Long

   Dim l As Long

   For l = 0 To FieldCount - 1
     If StrComp(Name, mFields(FIELDS_NAME_INDEX, l), vbTextCompare) = 0 Then
       GetFieldIndex = l
       Exit Function
     End If
   Next

   If Add Then
     If FieldCount = UBound(mFields, 2) Then
       ReDim Preserve mFields(1, UBound(mFields, 2) + FIELDS_BUFFER_LENGTH)
     End If
     mFields(FIELDS_NAME_INDEX, FieldCount) = Name
     GetFieldIndex = FieldCount
     FieldCount = FieldCount + 1
   Else
     GetFieldIndex = -1
   End If

End Function

Private Function BuildRequest() As String

   Dim l As Long
   Dim s As String

   For l = 0 To FieldCount - 1
     s = s & URLEncode(mFields(FIELDS_NAME_INDEX, l)) & "=" & _
     URLEncode(mFields(FIELDS_VALUE_INDEX, l)) & "&"
   Next

   If Len(s) > 0 Then
     BuildRequest = Left$(s, Len(s) - 1)
   End If

End Function

Public Function URLEncode(Data As String) As String

   Dim l As Long
   Dim b() As Byte
   Dim s As String
   Dim c As String

   b = Data
      For l = 0 To UBound(b) Step 2
     If DontEncode(b(l)) Then
       s = s & Chr(b(l))
     Else
       c = Hex(b(l))
       While Len(c) < 2
         c = "0" & c
       Wend
       s = s & "%" & c
     End If
   Next

   URLEncode = s

End Function

Private Sub Class_Initialize()

   Dim l As Long

   ReDim mFields(1, FIELDS_BUFFER_LENGTH)

   For l = Asc("0") To Asc("9")
     DontEncode(l) = True
   Next
   For l = Asc("a") To Asc("z")
     DontEncode(l) = True
   Next
   For l = Asc("A") To Asc("Z")
     DontEncode(l) = True
   Next

End Sub

Private Sub Class_Terminate()

   Erase mFields

End Sub
<?php //yksinkertainen malli (tsekkaa.php)
//(lätki tämä web-hotellisi servulle)

   if(!isset($_POST["lisenssi"]))
   {
     $serial = $_GET["lisenssi"];
     $mysql_host = "mysql_palvelimesi";
     //(web-hotelleissa monesti: localhost)
     $mysql_user = "mysql_tunnuksesi";
     $mysql_password = "mysql_salasanasi";
     $mysql_database = "Tietokanta";
     $conn = mysql_connect($mysql_host, $mysql_user,
     $mysql_password) or die(mysql_error());
     mysql_select_db($mysql_database, $conn) or die(mysql_error());
     $sql = "SELECT * FROM taulu WHERE serial='$serial'";
     $result = mysql_query($sql, $conn) or die(mysql_error());

     if (mysql_fetch_row($result)==null)
     {

       echo "nolicense";
     }
     else
     {
       $today =  date( "Y-m-d H:m:s");

        if  (mysql_result($result, 0, "started") == null ||
        mysql_result($result, 0, "started") == "0000-00-00 00:00:00" )
        {
           $datex =  strtotime(date("Y-m-d H:m:s", strtotime($today)) . "+1 year");
           $datex = date('Y-m-d', $datex);
           $sql = "UPDATE taulu SET started='$datex' WHERE serial='$serial'";
           $result2 = mysql_query($sql, $conn) or die(mysql_error());
        }
        else
        {
           $expiration = mysql_result($result, 0, "started");
           $fullDays = date_diff($today, $expiration);
           if ((int)$fullDays <= 0)
           {
              echo "expired";
           }
           elseif((int)$fullDays > 0 && (int)$fullDays < 11)
           {
              echo "daysleft" + $fullDays;
           }
         }
      }
   }

   function date_diff($start, $end="NOW")
   {
      $sdate = strtotime($start);
      $edate = strtotime($end);

      $time = $edate - $sdate;
      if($time>=86400) {
         $pday = ($edate - $sdate) / 86400;
         $preday = explode('.',$pday);
         $timeshift = $preday[0];
      }
      return $timeshift;
   }
?>

Deffi [08.02.2011 10:27:49]

#

jtha kirjoitti:

Hyviä mielipiteitä.

Kuitenkin, jos joku viitsii vaikka murtaa tuon, niin ilmoittakaa kauanko meni, tarjoan kaljan vaikka sen peliprojektin julkistamistilaisuudessa.

(http://www.jth-automaatio.fi/ohj_putka_jtha.zip)

Selvitin käyttämäsi algoritmin. Sen muuttaminen käänteiseksi (jos tarvitsee) pitäisi olla triviaalia, enkä nyt kerkeä tehdä sitä. Joku tunti meni, ois menny paljon vähemmän jos toi olis ollut koodattu millä tahansa muulla kuin VB:llä (joka sylkee ihan käsittämätöntä binääriä)

http://fpaste.dy.fi/lF/dl binääri. oma "koodaajani", joka tekee saman kuin sinun ohjelmasi

Sorsa:

#include <stdio.h>
#include <stdlib.h>

#define RND_FILE "el_m_draw_varmuuskoodit.rnd"
#define MAGIC1 0x0c350
#define MAGIC2 0x0e7ef0

int main(int arcg, char *argv[])
{
    FILE *rndf;
    int sz;
    unsigned char *rnd;

    printf("OPtemp.exe keygen\n");

    if(!(rndf = fopen(RND_FILE, "r"))) {
        printf("%s ei aukee\n", RND_FILE);
        return -1;
    }

    fseek(rndf, 0, SEEK_END);
    sz = ftell(rndf);
    /*if(sz != 0x0f4240) {
        printf("väärän kokoinen %s\n", RND_FILE);
        return -1;
    }*/
    rnd = malloc(sz);
    fseek(rndf, 0, SEEK_SET);
    fread(rnd, 1, sz, rndf);
    fclose(rndf);

    while(1) {
        unsigned int i, idx, ebp18, edi;
        unsigned char input[256];

        printf("nimi kiitos: ");
        scanf("%255s", input);

        for(ebp18 = i = 0; i < strlen(input); i++)
            ebp18 = input[i]%0x7b + ebp18;

        for(i = 0; i < strlen(input); i++) {
            idx = ((input[i]*(i+1) + ebp18) % sz);
            edi = MAGIC1;
            while(edi <= MAGIC2) {
                idx = (edi - rnd[idx]*(i+1)) % sz;

                idx = (edi + rnd[idx]*(i+1)) % sz;
                edi += MAGIC1;
            }

            printf("%c", (rnd[idx] % 0x64) + 0x21);
        }
        printf("\n");
    }
    return 0;
}

HUOM!! Jos koodattuun merkkijonoon tulee erikoismerkkejä (esimerkiksi ääkkösiä), niin jtha:n ohjelma ei näytä niitä oikein.

jtha [08.02.2011 11:54:08]

#

Kiitos, Deffi. Kaljalasku paisuu.

Nea, kiitos koodista ja vinkistä. Monesti tuolla teollisuudessa ei ole nettiä käytössä ja ohjelmaa käytetään mm. halleissa ja tuotantotiloissa, joten yritän vielä tsempata ja hankaloittaa kopiointia tikulta toiseen tai tikulta koneelle.

Blaze [08.02.2011 12:44:26]

#

Tai sitten unohdat natseilun ja paat koko roskan avoimena lähdekoodina jakoon. "Teollisuuden hallit ja tuotantotilat" erityisesti kuulostaa siltä, että joku saattais tuohon jossain vaiheessa haluta jotain räätälöintiä, sitähän voit sitten myydä hyvään tuntihintaan.

Deffi [08.02.2011 15:01:05]

#

"Teollisuuden hallit ja tuotantotilat" kuulostaa vähän siltä, ettei kukaan lähde kräkkäämään sellaista. Varsinkin jos ohjelma on suomenkielinen. Tulevaisuus näyttää kräkkerien kannalta muutenkin tosi tylsältä, koska kaikki softa on menossa vapaampaan ja ilmaiseen suuntaan! :(

jtha [08.02.2011 16:09:55]

#

[OHI AIHEEN]
En ole omalla alallani moista huomannut? Kaikesta joutuu maksamaan, niin suunnittelu- kuin ohjelmointisoftistakin(logiikkaohjelmointi).

En osaa kuvitella, että tässä markkinataloudessa kukaan tekisi töitä ilmaiseksi tai jakaisi tuotteita(softaa) ilmaiseksi, ellei siihen sisälly joku muuta kautta saavutettava hyöty.

PS:
En haluaisi viittauksia natsismista tai muuta arvostelua tämän vuoksi. Eikös Ohjelmointiputkan hieno idea ole tässä, että keskustelemme asioista ja opimmekin jotakin. Pysytään vaan asiassa ja jos jokin yksityiskohta ottaa aiheessa/keskustelijassa päähän niin ei tarvitse osallistua ko. keskusteluun - vai mitä?
[/OHI AIHEEN]

Metabolix [08.02.2011 16:18:20]

#

Avoimen lähdekoodin ohjelmaa voi aivan hyvin myös myydä, ja lisäksi voi veloittaa tuesta ja pyydettyjen muutosten toteuttamisesta.

Grez [08.02.2011 17:07:21]

#

jtha kirjoitti:

En haluaisi viittauksia natsismista tai muuta arvostelua tämän vuoksi.

Jep jep, natseilullahan toki ei voi viitata muuhun kuin natsismiin, siksi kielioppinatsikin on aina tällaisia http://www.youtube.com/watch?v=N4vf8N6GpdM

groovyb [08.02.2011 18:05:42]

#

Itse en ainakaan tee open sourcea teollisuuteen (tai ylipäänsä ammattikayttöön). Niillä on varaa myös maksaa,ja vähentävät vielä verotuksessa. Sen päälle sitten vielä tuki,päivitykset ja räätälöinnit. Lahjoitan ennemmin vaikka spr:än tilille jos siltä tuntuu.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta