Sunday, September 26, 2010

example.smali

this is a basic example of smali code with some comments. view it with ultraedit and syntax highlighting to get the full effect. this file is also included and updated in lesson 0 of the way of the android cracker.

for reference of dalvik opcodes, visit Dalvik opcodes.

update: if you like this, you may also want to see some example structures.

update #2:  threw in a little bit about primitives and arrays.

# class name, also determines file path when dumped
.class public Lcom/packageName/example;

# inherits from Object (could be activity, view, etc.)
# note class structure is L;
.super Ljava/lang/Object;

# original java file name
.source "example.java"


# these are class instance variables
.field private someString:Ljava/lang/String;

# finals are not actually used directly, because references
# to them are replaced by the value itself
# primitive cheat sheet:
# V - void, B - byte, S - short, C - char, I - int
# J - long (uses two registers), F - float, D - double
.field public final someInt:I  # the :I means integer
.field public final someBool:Z # the :Z means boolean

# Do you see how to make arrays?
.field public final someCharArray:[C
.field private someStringArray:[Ljava/lang/String;


# this is the <init> of the constructor
# it calls the <init> of it's super, which in this case
# is Ljava/lang/Object; as you can see at the top
# the parameter list reads: ZLjava/lang/String;I
# Z - boolean
# Ljava/lang/String; - java String object
#   (semi-colon after non-primitive data types)
# I - integer
#   (no semi-colon)
# also notice this constructor returns V, which means void
.method public constructor <init>(ZLjava/lang/String;I)V
 # declare how many variable spaces we will need
 # we can have: v0, v1, v2, v3, v4 and v5 as variables.
 # smali/baksmali by default uses .registers
 # but you can change this by using --use-locals
 # apktool uses --use-locals and --sequential-labels
 .locals 6

 # these are not always present and are usuaully taken
 # out by optimization/obfuscation but they tell us
 # the names of Z, Ljava/lang/String; and I before
 # when it was in Java
 .parameter "someBool"
 .parameter "someInt"
 .parameter "exampleString"
 
 # the .prologue and .line directives can be mostly ignored
 # sometimes line numbers are useful for debugging errors
 .prologue
 .line 10
 
 # p0 means parameter 0
 # p0, in this case, is like "this" from a java class.
 # we are calling the constructor of our mother class.
 # what would p1 be?
 invoke-direct {p0}, Ljava/lang/Object;-><init>()V
 
 # store string in v0
 const-string v0, "i will not fear. fear is the mind-killer."
 
 # store 0xF hex value in v0 (or 15 in base 10)
 # this destroys previous value string in v0
 # variables do not have types they are just registers
 # for storing any type of value.
 # hexadecimal is base 15 is used in all machine languages
 # you normally use base 10
 # read up on it:
 # http://en.wikipedia.org/wiki/Hexadecimal
 const/4 v0, 0xF
 
 # create instance of StringBuilder in v1
 new-instance v1, Ljava/lang/StringBuilder;
 
 # initialize StringBuilder with v2
 # notice it returns V, or void
 const-string v2, "the spice must flow"
 invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
 
 # append p1, which is our first paramater and is boolean
 # therefore we use append(Z)
 # notice how append returns a StringBuilder
 invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;
 
 # use move-result-object to store previous result in v1
 move-result-object v1
 # non-objects use move-result or move-result-wide

 # append v2 to our StringBuilder
 # notice how this append takes a string and not Z
 const-string v2, "some random string"
 invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
 move-result-object v1
  
 # call toString() on our StringBuilder
 # if you use Java you know that most objects have toString()
 invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
 move-result-object v1
 
 # send our new string to the log.
 # this can be used to debug and can be picked up with ddms, logcat
 # or log collector. as an exercise look up what the d() function does
 # in the android developer documentation.
 const-string v0, "Tag"
 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
 move-result v0
 
 # get the current time in milliseconds
 # J denotes a float or wide return value
 invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
 move-result-wide v2
 # note!! since it is a wide value, it takes up v2 AND v3

 # so we must use v4 next
 # try to reuse variables if possible.
 const-wide/16 v4, 0x300 # this takes up v4 and v5
 div-long/2addr v2, v4   # divide v2 by v4
 long-to-int v2, v2      # convert v2 to an integer
 
 # since i wrote this in my head, there was no Java
 # compiler to add the .line's in the right places
 # but normally they would relate to actual Java lines
 # these are often removed with proguard optimization
 .line 12
 
 # store p1 as an instance variable (someBool) for this class
 # in java this may look like this.someBool = p1;
 iput-boolean p1, p0, Lcom/packageName/example;->someBool:Z
 
 .line 14
 
 # do the same for p3 and someInt
 iput p3, p0, Lcom/packageName/example;->someInt:I
 
 
 # get the value from p0.someInt
 iget v0, p0, Lcom/packageName/example;->someInt:I
 
 # now we will invoke a static method.
 # {} means empty parameters then the full package name followed by ->
 # then the method and it's return value. everything must be there.
 invoke-static {}, Lcom/packageName/example;->someMethod()Ljava/lang/String;
 
 # for different types of invoke-*, try this:
 # http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html
 # invoke-virtual and direct take the class instance as a first parameter.
 
 .line 16
 return-void # meditate on the void.
.end method

# try and figure this one out
.method public static someMethod()Ljava/lang/String;
 # could i have used fewer variables?
 .locals 4
 
 new-instance v0, Ljava/lang/Long;
 
 invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
 move-result-wide v1
 
 invoke-direct {v0, v1, v2}, Ljava/lang/Long;-><init>(J)V
 
 invoke-static {v0}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;
 move-result-object v1
 
 # notice use of return-object and not just return
 return-object v1
.end method

72 comments :

  1. I can't believe there are no more comments here. VERY helpful. I'm trying to dig into smali files and it's sometimes frustrating. Digging the Dune references there also ;)

    Since you are already doing this:
    what does if-eqz v4, :cond_2 mean?
    I'm trying to translate it in my mind to java:
    if (v4==0)
    (whatever is after the :cond_2 tag)
    else
    (whatever set of instructions follows)

    Am I correct?

    ReplyDelete
    Replies
    1. Yes, if v4 is equal to zero go to the line where :cond_2 is placed and continue on from there,
      otherwise just continue on at the next line.

      Delete
    2. if you want to write if(v4==0) in smali

      if-nez v0, :cond_0
      //This block execute when Value in v0 is Zero

      :cond_0
      //This block execute when Value in v0 is One

      Delete
    3. Your thinking of if(v4!=0)

      For if-nez

      It should be if-eqz

      Delete
  2. i'm glad you find it helpful and you enjoy dune :D.

    you are correct. it helps to mentally read it as "if equals zero v4 jump to label :cond_2". this goto-style branching is typical of lower level languages.

    ReplyDelete
  3. Thanks for the quick reply
    I was figuring it out myself in the meantime. In this case v4 is a Z (boolean as I learned today :), so I'm assuming it could be read as if (!v4), which would make sense in the context of the rest of the code.

    I will go over your lessons 0 and 1. I'll probably come with a few more questions after that if you don't mind.

    ReplyDelete
  4. Thanks a LOT! This is really helpful!

    ReplyDelete
  5. OMG!!!! Thank u for this great work. The comment is really helpful to me. Great Job. Thank you

    ReplyDelete
  6. I'm working on project which is based on baksmali but outputs java-code instead of smali-code, because it's much easier than smali and there is no application around which produces compileable java-code(dex2jar is very buggy).

    I already got simple classes and method-definitions converted but now I'm about to convert variables.

    So I need to know how this works exactly :)
    One problem I have is the number behind "const/" which always differs. what does it mean?

    Maybe you can contact me via email so I don't have to go offtopic in the comments.

    ReplyDelete
    Replies
    1. Hi, have you finished the project, coz I badly need that now, not only me so many developers are waiting forward for suc sort of project which could directly convert to java files and you are absolutely right about dex2jar, but there are no further improvements or later versions released in that. So looking eagerly forward for your project.

      Delete
    2. hi, did you manage to find the meaning of the numbers behind the "const/" ?

      Delete
    3. It refers to the number of bits for the literal. const/4 would be 4 bits sign extended to 32 bits. See http://source.android.com/tech/dalvik/dalvik-bytecode.html for more information.

      Delete
    4. const/4
      means that reister size is 4 bytes

      Delete
  7. Hi, lohan+

    I'm writing a tutorial on android malware analysis here:
    http://code.google.com/p/amatutor

    I hope it can use your code in example.smali, example-structures.java, and example-structure.smali to introduce smali syntax and dalvik opcode to readers. Because current version is writen by Chinese, I hope I can delete some comments and explain it in Chinese.
    I will add your name and the refer URLs near these code.

    Can I use it like that? Hope for your confirm email, my address is iClaudXiao@gmail.com
    Thank u very much.

    Claud Xiao

    ReplyDelete
  8. Hi there can u please help me in writing coding in smali format to add an edittext...??

    ReplyDelete
  9. how important is ".line"?

    # .line directives can be mostly ignored
    # sometimes line numbers are useful for debugging errors

    .line 10

    based on your comment .line it's used mostly for error debug?
    or some code it's called through that ".line"?
    thanks!

    ReplyDelete
  10. No code is called. It's just debugging information. It shows up in error logs and stack dumps

    ReplyDelete
  11. This is great helpful!Thank you!

    ReplyDelete
  12. Thanks for the interesting info.
    A small correction: it should be "15 in base 10" on line 68 ;)

    ReplyDelete
  13. In line 68 and line 72, don't you mean 16? :)

    ReplyDelete
  14. I made the same mistake originally. You'll notice the comment above yours corrected it. Intuitively, the maximum value of a single digit in base 10 can only be 9. 0x9 = 9, 0xA = 10, 0xB = 11, 0xC = 12, 0xD = 13, 0xE = 14, 0xF = 15

    ReplyDelete
  15. Do you know if its possible to link in libraries that weren't included in the original build?
    ex. if you add a log statement and Landroid/util/Log results in a ClassDefNotFound

    ReplyDelete
  16. Explanations through your comments were really helpful...thanks

    ReplyDelete
  17. Anonymous, short answer: go ahead, shouldn't be a problem.
    long answer: you will only get ClassDefNotFound if the class is not available to the class loader. if you're referring to java's adding of "import" statements, those are not really present in the bytecode, so i'm guessing they're just there to help the compiler know what you're referring to. if you're on a normal android system Landroid/util/Log will be there.

    ReplyDelete
  18. dude you are awesome i need to contact you

    ReplyDelete
  19. Dude, you just made things A LOT less of a headache! I can't thank you enough for this!

    ReplyDelete
  20. Helped me alot here but sadly im still stuck not sure what the goto or cond tags are for i see in a comment they mean to like jump somewhere

    ReplyDelete
  21. I am just a begineer. and i am trying to edit an app that send "call me back" message to a phoe number that i entered but it don't list my contact list. A problem of that app is i need to remember phone number that i want message to. So what i want to know is how to list phone contact list and use it in .smali file. thank you.

    ReplyDelete
  22. This very very helpfull, thanks brothers, i am newbe and wanted to learn

    ReplyDelete
  23. This very very helpfull, thanks brothers, i am newbe and wanted to learn

    ReplyDelete
  24. Hi sir how can I create an int array in smali?

    In java I do this COLOR_ARRAY = new int[]{Color.rgb(int, int, int), Color.rgb(int, int, int), Color.rgb(int, int, int), Color.rgb(int, int, int)}

    How to do this in smali?

    ReplyDelete
    Replies
    1. best way is to actually learn how to convert arbitrary java to smali.
      1.) write the code in java and compile using javac. this will create .class files.
      2.) compile .class files using dx (part of android sdk) into a .dex file
      3.) baksmali the dex file to get the smali
      4.) automate this using aliases and functions in bash

      Delete
  25. Hello. I want to make this method return a "false" value.
    .method public isLocked()Z
    .locals 1
    iget-boolean v0, p0, Lahc;->isLocked:z
    return v0
    .end method

    ReplyDelete
    Replies
    1. replace "iget-boolean ..." with "const/4 v0"
      better would be to find where isLocked is set and fix it so it's set to true. you don't know where else that field is getting checked. may be through reflection and not obvious with static analysis.

      Delete
  26. What is the use of smali? Pls explain briefly...

    ReplyDelete
    Replies
    1. smali is how the bytecode of dalvik executables can be represented. it's good because it's easy to modify and read. most of the time you don't use it directly. you only "use" it when you need to read and modify it. though it's entirely possible to write programs purely in smali and compile them to dalvik executables using smali. you can also write java, convert to java class files (javac), then convert to dalvik (dx) then convert back to smali.

      Delete
  27. As the job seekers does not only rely on the employment news, they also expect information related to the exam as well as the sarkari results which we find here very apt.

    ReplyDelete
  28. That was a wonderful article. Smali material on the internet is very scarce and this article is a perfect place to get started. Btw, I had a question (though I will follow-up with more questions): When I try to print the byte array using toString() function, I get an overflow error on logcat. Is there a way to get around and print the byte array contents? Any short cuts, hacks? Thanks in advance.

    ReplyDelete
  29. This comment has been removed by the author.

    ReplyDelete
  30. This comment has been removed by the author.

    ReplyDelete
  31. when i try crack app after change smali code and building and singing i installed it the app open for 2 or 3 second then automatically close can u tell me why

    ReplyDelete
  32. this is very very very helpful!!!
    thx a lot!!

    ReplyDelete
  33. wow, great work. thanks for info

    ReplyDelete
  34. I do not understand the code. Many people who write code is very good at it. I do not write it. สมัครบาคาร่า

    ReplyDelete
  35. Your blog is great. Great to see your new posting. Thank for the sharing.

    ReplyDelete
  36. Can't thank you enough, man! Helped me understand smali a lot! Have a great day :)

    ReplyDelete
  37. Portal blog pribadi salah satunya adalah wasimaf.wordpress.com yang menyajikan konten pendidikan, kesehatan, bisnis dan blogger untuk pemirsa yang menyukai dan setia membaca karya wasimaf sepanjang waktu. Wasimaf hadir dengan tampil beda dengn yang lain dengan menggunakan metode penyampaian yang mudah dimengerti oleh anak muda maupun orang tua sekalipun.

    Diantara konten wasimaf adalah tentang bimtek yang barupa keuangan daerah mengatur langkah-langkah dan prosedur untuk meningkatkan kualitas manajemen keuangan daerah yang baik. Untuk SKPD / OPD, implementasi aktual dari sistem dan prosedur baik untuk daerah masing-masing Seperti Sistem dan Prosedur Penerimaan, Biaya dan Prosedur dan Sistem dan Prosedur Akuntansi Info bimtek pusdiklat pemendagri keuangan pemerintah daerah. Konsekuensi dari penerbitan Permendagri 64/2013 adalah komitmen pemerintah daerah untuk mengatur kepala daerah yang mengatur kebijakan akuntansi pemerintah.

    Istilah shortlink dan safelink sudah dikenal oleh beberapa blogger. Kedua hal ini juga bermanfaat untuk mengurangi kerja beberapa blogger. Terutama blogger yang fokus pada konten yang diunduh (unduhan blog). Fungsi Safelink blogger sebenarnya sama, perbedaannya hanya pada cara kerjanya. Berikut ini adalah komentar tentang pemahaman dan perbedaan antara dua hal.

    Diantara layanan yang diberikan oleh "Safelink Blogger" adalah sistem pembayaran secara Cost Per Miles (CPM) kepada penggunanya. Sebelum mengulas lebih jauh terkait pembayaran Safelink Blogger (SB), mari bahas satu persatu beberapa fitur safelink blogger, fungsi, cara kerja dan manfaat safelink blogger.

    Selain itu wasimaf menjelaskan tentang Greek yogurt tinggi protein dimana produk ini merupakan satu dari beraneka ragam produk yogurt yang berbeda dengan yogurt jenis lainnya, karena "greek yogurt tinggi protein" memiliki tekstur kental, tetapi tetap lunak sehingga aman dikonsumsi oleh semua umur baik dewasa, remaja maupun anak-anak.

    Proses pembuatan Greek yogurt tinggi protein berbeda dengan yogurt biasa, dimana Greek yogurt ini dibuat dengan proses penyaringan sehingga teksturnya lebih kental.

    Greek yogurt untuk menghilangkan air limbah, menghasilkan bentuk yang lebih padat daripada non-beku, sambil tetap melayani kekhasan yogurt, rasa asam. Seperti beberapa jenis yogurt, yogurt sering dibuat dari susu kaya dengan merebus sebagian isi air dan / atau menambahkan lemak mentega dan susu bubuk. Di Eropa dan Amerika Utara, yogurt sering dibuat dengan yogurt rendah lemak atau bebas gula. Di Skandinavia, terutama di Islandia, produk serupa diproduksi.

    Wasimaf, ketua PT Asuransi Mitsui Sumitomo Insurance Group Indonesia, mengatakan surplus perusahaan asuransi melebihi target, tetapi tidak menyebutkan nilainya. Hingga kuartal ketiga 2015, "Asuransi kendaraan MSIG, berkendara tanpa cemas" merupakan produk utamanya barang dengan komposisi 57,3% dari total kuantitas dan kargo laut sekitar 18,6%.

    Menurut wasimaf, Grup Asuransi Mitsui Sumitomo (MSIG), yang beroperasi sebagai perusahaan asuransi umum, telah menghadapi tantangan pada tahun 2015 karena aturan OJK yang baru, terutama Asuransi kendaraan MSIG, berkendara tanpa cemas kelas asuransi properti dan kendaraan bermotor. Dalam publikasinya, Indonesia dianggap berpotensi mampu mengembangkan dan menjanjikan industri asuransi, jika dilihat dari pemberontakan bisnis asuransi masih minim.

    ReplyDelete
  38. Istilah shortlink dan safelink sudah dikenal oleh beberapa blogger. Kedua hal ini juga bermanfaat untuk mengurangi kerja beberapa blogger. Terutama blogger yang fokus pada konten yang diunduh (unduhan blog). Fungsi Safelink blogger sebenarnya sama, perbedaannya hanya pada cara kerjanya. Berikut ini adalah komentar tentang pemahaman dan perbedaan antara dua hal. selain itu blog ini juga sering ikut kontes seo terbaru yang diadakan perorangan atau perusahaan

    ReplyDelete
  39. Portal blog pribadi salah satunya adalah ciebal.web.id yang menyajikan konten pendidikan, kesehatan, bisnis dan blogger untuk pemirsa yang menyukai dan setia membaca karya wasimaf sepanjang waktu. Wasimaf hadir dengan tampil beda dengn yang lain dengan menggunakan metode penyampaian yang mudah dimengerti oleh anak muda maupun orang tua sekalipun.

    Istilah shortlink dan safelink sudah dikenal oleh beberapa blogger. Kedua hal ini juga bermanfaat untuk mengurangi kerja beberapa blogger. Terutama blogger yang fokus pada konten yang diunduh (unduhan blog). Fungsi Safelink blogger sebenarnya sama, perbedaannya hanya pada cara kerjanya. Berikut ini adalah komentar tentang pemahaman dan perbedaan antara dua hal.

    Diantara layanan yang diberikan oleh "Safelink Blogger" adalah sistem pembayaran secara Cost Per Miles (CPM) kepada penggunanya. Sebelum mengulas lebih jauh terkait pembayaran Safelink Blogger (SB), mari bahas satu persatu beberapa fitur safelink blogger, fungsi, cara kerja dan manfaat safelink blogger.

    Selain itu wasimaf menjelaskan tentang Greek yogurt tinggi protein dimana produk ini merupakan satu dari beraneka ragam produk yogurt yang berbeda dengan yogurt jenis lainnya, karena "greek yogurt tinggi protein" memiliki tekstur kental, tetapi tetap lunak sehingga aman dikonsumsi oleh semua umur baik dewasa, remaja maupun anak-anak.

    Proses pembuatan Greek yogurt tinggi protein berbeda dengan yogurt biasa, dimana Greek yogurt ini dibuat dengan proses penyaringan sehingga teksturnya lebih kental.

    Greek yogurt untuk menghilangkan air limbah, menghasilkan bentuk yang lebih padat daripada non-beku, sambil tetap melayani kekhasan yogurt, rasa asam. Seperti beberapa jenis yogurt, yogurt sering dibuat dari susu kaya dengan merebus sebagian isi air dan / atau menambahkan lemak mentega dan susu bubuk. Di Eropa dan Amerika Utara, yogurt sering dibuat dengan yogurt rendah lemak atau bebas gula. Di Skandinavia, terutama di Islandia, produk serupa diproduksi.

    Wasimaf, ketua PT Asuransi Mitsui Sumitomo Insurance Group Indonesia, mengatakan surplus perusahaan asuransi melebihi target, tetapi tidak menyebutkan nilainya. Hingga kuartal ketiga 2015, "Asuransi kendaraan MSIG, berkendara tanpa cemas" merupakan produk utamanya barang dengan komposisi 57,3% dari total kuantitas dan kargo laut sekitar 18,6%.

    Menurut wasimaf, Grup Asuransi Mitsui Sumitomo (MSIG), yang beroperasi sebagai perusahaan asuransi umum, telah menghadapi tantangan pada tahun 2015 karena aturan OJK yang baru, terutama Asuransi kendaraan MSIG, berkendara tanpa cemas kelas asuransi properti dan kendaraan bermotor. Dalam publikasinya, Indonesia dianggap berpotensi mampu mengembangkan dan menjanjikan industri asuransi, jika dilihat dari pemberontakan bisnis asuransi masih minim.

    ReplyDelete
  40. Baik pemangku kebijakan kepegawaian atau pun pegawai itu sendiri khususnya PNS (Pegawai Negeri SIpil). Penting bagi seorang PNS untuk mengikuti info Bimtek Pusdiklat Pemendagri untuk mengetahui semua info diklat yang dibutuhkan. Untuk Bimtek Kepegawaian materi yang diberikan juga khusus untuk kepegawaian, ini ulasannya.Info Bimtek Pusdiklat Pemendagri

    ReplyDelete
  41. 1. Aries (March 21 - April 20) Concentrate on your money problem and how to save it. However, this will not be a burden for you. It's good not to neglect household chores when you find a moody partner. So, continue to do as you planned. Don't cancel it.

    ReplyDelete
  42. an amazing information shared by the author with details post.
    thank you for sharing such informative information
    sarkari samachar
    fssai result
    kv challan
    htet online

    ReplyDelete
  43. Có ai làm ơn giúp tôi. Tôi đã cố 3 tuần nay nhưng không làm được.
    .field public a:Ljava/util/List;
    .annotation runtime Lb/g/c/a0/b;
    value = "app_state"
    .end annotation
    .end field

    .method public constructor (Ljava/util/List;Ljava/lang/Integer;)V
    .registers 3


    .line 1
    invoke-direct {p0}, Lb/a/a/q/b;->()V

    .line 2
    iput-object p1, p0, Lb/a/a/q/h/c/b;->a:Ljava/util/List;

    .line 3
    iput-object p2, p0, Lb/a/a/q/h/c/b;->b:Ljava/lang/Integer;
    return-void
    .end method


    "p2" Is "app_state" value. If I use this app(this app is on-screen). It send to server this code

    {"app_state":1}

    If this app run in backgroud, it send to sever a code

    {"app_state":3}
    But I just want the value alway is "app_state":3. Please help me

    O try "const p2, 0x3" but it don't work

    ReplyDelete
  44. Hi I am trying hard to do the follow.
    i have this string

    const-string v2, "http://www.example.com/?macaddress="
    how i will append to the string the macaddress or the deviceinfo ???????

    thanks for your time




    ReplyDelete
  45. Коллекция, последние новости, онлайн-новости, потоковое, доверенное, вирусные новости, путешествия, закон
    seteguk nikmat berita

    ReplyDelete
  46. It is generous of you to share all that knowledge. Thank you for visiting my website again. Also, Check BSc 3rd Year Result

    ReplyDelete
  47. Excellent post. Keep posting such kind of information on your blog.
    HINDI BARKHADI

    ReplyDelete
  48. Nice to read your blog post. There is good information in your blog, I got good ideas from this wonderful blog. I am always looking for this type of blog post , and also find various profile jobs by job vacancy result
    Jobs in mumbai
    Jobs in mumbai
    Jobs in mumbai
    Jobs in mumbai

    ReplyDelete
  49. I am very thankful to you for providing such a great information. It is simple but very accurate information.

    ReplyDelete

Do NOT post about or link to specific apps!